Execute an operation that might fail and returns its result, or raise the exception that was thrown depending on the `Backoff` object. `do`: the operation to call. Expects no argument. `fail`: the failure handler, expects the last error that was thrown ``is_r
(
self,
do: Callable[[], T],
fail: Union[Callable[[Exception], Any], Callable[[Exception, int], Any]],
is_retryable: Optional[Callable[[Exception], bool]] = None,
with_failure_count: bool = False,
)
| 99 | ) |
| 100 | |
| 101 | def call_with_retry( |
| 102 | self, |
| 103 | do: Callable[[], T], |
| 104 | fail: Union[Callable[[Exception], Any], Callable[[Exception, int], Any]], |
| 105 | is_retryable: Optional[Callable[[Exception], bool]] = None, |
| 106 | with_failure_count: bool = False, |
| 107 | ) -> T: |
| 108 | """ |
| 109 | Execute an operation that might fail and returns its result, or |
| 110 | raise the exception that was thrown depending on the `Backoff` object. |
| 111 | `do`: the operation to call. Expects no argument. |
| 112 | `fail`: the failure handler, expects the last error that was thrown |
| 113 | ``is_retryable``: optional function to determine if an error is retryable |
| 114 | ``with_failure_count``: if True, the failure count is passed to the failure handler |
| 115 | """ |
| 116 | self._backoff.reset() |
| 117 | failures = 0 |
| 118 | while True: |
| 119 | try: |
| 120 | return do() |
| 121 | except self._supported_errors as error: |
| 122 | if is_retryable and not is_retryable(error): |
| 123 | raise |
| 124 | failures += 1 |
| 125 | |
| 126 | if with_failure_count: |
| 127 | fail(error, failures) |
| 128 | else: |
| 129 | fail(error) |
| 130 | |
| 131 | if self._retries >= 0 and failures > self._retries: |
| 132 | raise error |
| 133 | backoff = self._backoff.compute(failures) |
| 134 | if backoff > 0: |
| 135 | sleep(backoff) |