25
25
import time
26
26
27
27
from enum import Enum
28
- from typing import Any , Callable , Optional , TYPE_CHECKING
28
+ from typing import Any , Callable , Optional , Iterator , TYPE_CHECKING
29
29
30
30
import requests .exceptions
31
31
@@ -174,7 +174,7 @@ def build_retry_error(
174
174
def _retry_error_helper (
175
175
exc : Exception ,
176
176
deadline : float | None ,
177
- next_sleep : float ,
177
+ sleep_iterator : Iterator [ float ] ,
178
178
error_list : list [Exception ],
179
179
predicate_fn : Callable [[Exception ], bool ],
180
180
on_error_fn : Callable [[Exception ], None ] | None ,
@@ -183,7 +183,7 @@ def _retry_error_helper(
183
183
tuple [Exception , Exception | None ],
184
184
],
185
185
original_timeout : float | None ,
186
- ):
186
+ ) -> float :
187
187
"""
188
188
Shared logic for handling an error for all retry implementations
189
189
@@ -194,13 +194,15 @@ def _retry_error_helper(
194
194
Args:
195
195
- exc: the exception that was raised
196
196
- deadline: the deadline for the retry, calculated as a diff from time.monotonic()
197
- - next_sleep: the next sleep interval
197
+ - sleep_iterator: iterator to draw the next backoff value from
198
198
- error_list: the list of exceptions that have been raised so far
199
199
- predicate_fn: takes `exc` and returns true if the operation should be retried
200
200
- on_error_fn: callback to execute when a retryable error occurs
201
201
- exc_factory_fn: callback used to build the exception to be raised on terminal failure
202
202
- original_timeout_val: the original timeout value for the retry (in seconds),
203
203
to be passed to the exception factory for building an error message
204
+ Returns:
205
+ - the sleep value chosen before the next attempt
204
206
"""
205
207
error_list .append (exc )
206
208
if not predicate_fn (exc ):
@@ -212,6 +214,12 @@ def _retry_error_helper(
212
214
raise final_exc from source_exc
213
215
if on_error_fn is not None :
214
216
on_error_fn (exc )
217
+ # next_sleep is fetched after the on_error callback, to allow clients
218
+ # to update sleep_iterator values dynamically in response to errors
219
+ try :
220
+ next_sleep = next (sleep_iterator )
221
+ except StopIteration :
222
+ raise ValueError ("Sleep generator stopped yielding sleep values." ) from exc
215
223
if deadline is not None and time .monotonic () + next_sleep > deadline :
216
224
final_exc , source_exc = exc_factory_fn (
217
225
error_list ,
@@ -222,6 +230,7 @@ def _retry_error_helper(
222
230
_LOGGER .debug (
223
231
"Retrying due to {}, sleeping {:.1f}s ..." .format (error_list [- 1 ], next_sleep )
224
232
)
233
+ return next_sleep
225
234
226
235
227
236
class _BaseRetry (object ):
0 commit comments