-
-
Notifications
You must be signed in to change notification settings - Fork 318
feat: deprecate initial in favor of multiplier in wait_exponential_jitter
#629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| --- | ||
| deprecations: | ||
| - | | ||
| The ``initial`` parameter of ``wait_exponential_jitter`` is deprecated in | ||
| favor of ``multiplier``, for consistency with ``wait_exponential``. Passing | ||
| ``initial`` still works but emits a ``DeprecationWarning``. | ||
| features: | ||
| - | | ||
| Add ``multiplier`` parameter to ``wait_exponential_jitter``, consistent | ||
| with ``wait_exponential``. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ | |
| import abc | ||
| import random | ||
| import typing | ||
| import warnings | ||
|
|
||
| from tenacity import _utils | ||
|
|
||
|
|
@@ -240,12 +241,12 @@ def __call__(self, retry_state: "RetryCallState") -> float: | |
| class wait_exponential_jitter(wait_base): | ||
| """Wait strategy that applies exponential backoff and jitter. | ||
|
|
||
| It allows for a customized initial wait, maximum wait, jitter and minimum. | ||
| It allows for a customized multiplier, maximum wait, jitter and minimum. | ||
|
|
||
| This implements the strategy described here: | ||
| https://cloud.google.com/storage/docs/retry-strategy | ||
|
|
||
| The wait time is max(min, min(initial * 2**n + random.uniform(0, jitter), maximum)) | ||
| The wait time is max(min, min(multiplier * 2**n + random.uniform(0, jitter), maximum)) | ||
| where n is the retry count. | ||
| """ | ||
|
|
||
|
|
@@ -256,8 +257,22 @@ def __init__( | |
| exp_base: float = 2, | ||
| jitter: _utils.time_unit_type = 1, | ||
| min: _utils.time_unit_type = 0, | ||
| multiplier: float = 1, | ||
| ) -> None: | ||
| self.initial = initial | ||
| if initial != 1 and multiplier != 1: | ||
| raise ValueError( | ||
| "Cannot specify both 'initial' and 'multiplier' — use 'multiplier' only" | ||
| ) | ||
|
|
||
| if initial != 1: | ||
| warnings.warn( | ||
| "The 'initial' parameter is deprecated, use 'multiplier' instead", | ||
| DeprecationWarning, | ||
| stacklevel=2, | ||
| ) | ||
|
Comment on lines
+267
to
+272
|
||
| multiplier = initial | ||
|
|
||
| self.multiplier = multiplier | ||
| self.max = _utils.to_seconds(max) | ||
| self.exp_base = exp_base | ||
| self.jitter = _utils.to_seconds(jitter) | ||
|
|
@@ -267,7 +282,7 @@ def __call__(self, retry_state: "RetryCallState") -> float: | |
| jitter = random.uniform(0, self.jitter) | ||
| try: | ||
| exp = self.exp_base ** (retry_state.attempt_number - 1) | ||
| result = self.initial * exp + jitter | ||
| result = self.multiplier * exp + jitter | ||
| except OverflowError: | ||
| result = self.max | ||
| return max(max(0, self.min), min(result, self.max)) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
ValueErrorguard only triggers when both arguments are non-default (initial != 1 and multiplier != 1). This means callers can still pass both parameters without an error wheninitialis explicitly provided as the default (e.g.wait_exponential_jitter(initial=1, multiplier=10)), which contradicts the PR's stated behavior. Consider using a sentinel/Nonedefault forinitial(or another way to detect whether it was provided) so you can reliably raise wheneverinitialis specified alongsidemultiplier.