Last active
July 22, 2016 14:25
-
-
Save inirudebwoy/2a33eb8a9cec464bff5b72540bc376db to your computer and use it in GitHub Desktop.
Decorator retrying connection with the callback on failure
This file contains hidden or 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(retries=3, callback_on_failure=None): | |
"""Retry requests method and run callback on failure | |
Decorator will retry the decorated function for specified number of times, | |
default is 3. If there is a callback passed, it will be called before | |
calling the decorated function again. Callback allows to perform cleanups, | |
clear the credentials, etc. | |
Decorator will only work with functions that return requests.Request | |
object, if decorated method returns other object result is returned with | |
out retrying. | |
Example: | |
def callback(result, exc): | |
if result.failed: | |
print('Cleaning up') | |
... | |
@retry(retries=2, callback_on_failure=callback) | |
def grab_data_from_external_source(): | |
return requests.get('https://i.like.chorizo.es') | |
If decorated function fails callback will be called before retrying. | |
:param retries: number of retries of decorated function (Default value = 3) | |
:type retries: int | |
:param callback_on_failure: callback function to run on failure of | |
decorated function (Default value = None) | |
:type callback_on_failure: func | |
""" | |
def decorate(func): | |
@wraps(func) | |
def wrapper(*args, **kwargs): | |
mretries = retries | |
while mretries > 0: | |
result = func(*args, **kwargs) | |
try: | |
result.raise_for_status() | |
except requests.HTTPError as exc: | |
logger.info( | |
'Retrying function call "{0}"'.format(func.func_name)) | |
logger.exception('HTTPError raised') | |
try: | |
logger.debug('Calling callback function.') | |
callback_on_failure(result, exc) | |
except TypeError: | |
# no callback, silence it | |
pass | |
except Exception as exc: | |
# catching every error raised by callback | |
logger.exception( | |
'Callback "{0}" raised an exception.'.format( | |
callback_on_failure.func_name)) | |
mretries -= 1 | |
except AttributeError: | |
logger.info('Result is not requests.Request type.') | |
return result | |
return result | |
return wrapper | |
return decorate |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment