Created
May 9, 2013 20:50
-
-
Save danielhfrank/5550523 to your computer and use it in GitHub Desktop.
Attempt at a retry-with-backoff decorator. May it (and I) rest in peace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def retry_with_backoff(method): | |
""" | |
The idea was to use this to decorate a method that makes some kind of request and has a callback | |
kwarg. The callback will be decorated to retry the calling function a few times, | |
with backoff, if it receives an error. | |
""" | |
@functools.wraps(method) | |
def caller_wrapper(self, *args, **kwargs): | |
callback = kwargs['callback'] | |
attempts = kwargs.pop('attempts', 0) | |
@functools.wraps(callback) | |
def callback_wrapper(*args, **kwargs): | |
error = test_and_get_error(args[0]) | |
if error and attempts < MAX_ATTEMPTS: | |
# Try the request again | |
retry_at = time.time() + INITIAL_DELAY * 2 ** attempts | |
kwargs['attempts'] = attempts + 1 | |
tornado.ioloop.IOLoop.instance().add_timeout(retry_at, | |
functools.partial(method, *args, **kwargs)) | |
else: | |
# Proceed with the callback, in good times or in bad | |
return callback(*args, **kwargs) | |
kwargs['callback'] = callback_wrapper | |
return method(self, *args, **kwargs) | |
return caller_wrapper | |
def test_and_get_error(data): | |
if isinstance(data, tornado.httpclient.HTTPResponse) and data.error: | |
return data.error | |
elif isinstance(data, Exception): | |
return data | |
return None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment