Skip to content

Commit

Permalink
fix(core): change KazooRetry to uniformly jitter over the whole backo…
Browse files Browse the repository at this point in the history
…ff interval (#521)

The previous implementation would add a fixed amount of jitter around
the calculated back-off time. Retry attempts were thus clustered
around the exponentially spaced backoff points.

This patch does exponential backoff but uniformly spreads the retries
over an interval [0, backoff**attempt]
  • Loading branch information
andreasgudmundsson authored and jeffwidman committed Sep 26, 2018
1 parent 35ce106 commit 60366d2
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 10 deletions.
2 changes: 0 additions & 2 deletions kazoo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,13 @@
max_retries=None,
retry_delay=0.1,
retry_backoff=2,
retry_jitter=0.8,
retry_max_delay=3600,
)

_RETRY_COMPAT_MAPPING = dict(
max_retries='max_tries',
retry_delay='delay',
retry_backoff='backoff',
retry_jitter='max_jitter',
retry_max_delay='max_delay',
)

Expand Down
11 changes: 3 additions & 8 deletions kazoo/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,17 @@ class KazooRetry(object):
SessionExpiredError,
)

def __init__(self, max_tries=1, delay=0.1, backoff=2, max_jitter=0.8,
def __init__(self, max_tries=1, delay=0.1, backoff=2,
max_delay=60, ignore_expire=True, sleep_func=time.sleep,
deadline=None, interrupt=None):
"""Create a :class:`KazooRetry` instance for retrying function
calls
calls with uniform jitter
:param max_tries: How many times to retry the command. -1 means
infinite tries.
:param delay: Initial delay between retry attempts.
:param backoff: Backoff multiplier between retry attempts.
Defaults to 2 for exponential backoff.
:param max_jitter: Additional max jitter period to wait between
retry attempts to avoid slamming the server.
:param max_delay: Maximum delay in seconds, regardless of other
backoff settings. Defaults to one minute.
:param ignore_expire:
Expand All @@ -70,7 +68,6 @@ def __init__(self, max_tries=1, delay=0.1, backoff=2, max_jitter=0.8,
self.max_tries = max_tries
self.delay = delay
self.backoff = backoff
self.max_jitter = int(max_jitter * 100)
self.max_delay = float(max_delay)
self._attempts = 0
self._cur_delay = delay
Expand All @@ -93,7 +90,6 @@ def copy(self):
obj = KazooRetry(max_tries=self.max_tries,
delay=self.delay,
backoff=self.backoff,
max_jitter=self.max_jitter / 100.0,
max_delay=self.max_delay,
sleep_func=self.sleep_func,
deadline=self.deadline,
Expand Down Expand Up @@ -129,8 +125,7 @@ def __call__(self, func, *args, **kwargs):
if self._attempts == self.max_tries:
raise RetryFailedError("Too many retry attempts")
self._attempts += 1
sleeptime = self._cur_delay + (
random.randint(0, self.max_jitter) / 100.0)
sleeptime = random.randint(0, 1 + int(self._cur_delay))

if self._cur_stoptime is not None and \
time.time() + sleeptime >= self._cur_stoptime:
Expand Down

0 comments on commit 60366d2

Please sign in to comment.