Skip to content

Instantly share code, notes, and snippets.

@lee-pai-long
Last active September 16, 2020 23:33
Show Gist options
  • Save lee-pai-long/4c622e4460ee0b97e3022fbe9e176aa1 to your computer and use it in GitHub Desktop.
Save lee-pai-long/4c622e4460ee0b97e3022fbe9e176aa1 to your computer and use it in GitHub Desktop.
Retry an action with exponential backoff
"""Retry an action with exponential backoff.
Inspired by:
- https://www.toptal.com/python/python-parameterized-design-patterns#classes-as-exceptions
- https://stackoverflow.com/a/33577016/3775614
"""
# WARNING: Never used yet
# TODO: Add a unit test module
import time
class MaxAttemptsReached(Exception):
"""Raised when retry_with_backoff max attempt is reach."""
def __init__(self, action, max_attempts):
"""MaxAttemptsReached
Arguments:
- action (callable): the attempted action
- max_attempts (int): the number of attempts tried before faulting to this
"""
self.message = "Max attempts {0} reached for action {1}".format(
max_attempts, getattr(action, '__name__', repr(action))
)
super().__init__(self.message)
def retry_with_backoff(
action,
exceptions,
max_attempts=10,
attempts_so_far=0
):
"""Retry an action with exponential backoff.
Attempt an action that could fail,
and retry with exponential backoff,
until a maximum number of attempts is reached.
Arguments:
- action (callable): The action to attempt
- exceptions (Exception or tuple): Can be any exception
or a tuple of exceptions to catch.
- max_attempts (int): The maximum attempt to try,
default: 10
- attempts_so_far (int): The current number of attempts,
mainly use for recursiveness,
default: 0
Returns:
- the result of {action} if it succeed,
or retries with a sleep time of {attempts_so_far ** 2}
"""
try:
return action()
except exceptions:
attempts_so_far += 1
if attempts_so_far >= max_attempts:
raise MaxAttemptsReached(action, max_attempts)
else:
time.sleep(attempts_so_far ** 2)
return retry_with_backoff(
action, exceptions, max_attempts, attempts_so_far
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment