-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathretryer.py
64 lines (53 loc) · 2.58 KB
/
retryer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# -*- coding: utf-8 -*-
"""Retryer.
A simple module with ``retryer``, a decorator that re-runs the decorated
function again after a sleep (blocking the current thread) in case of exception
during it's excecution.
"""
import logging
from time import sleep
logger = logging.getLogger(__name__)
class NetworkError(RuntimeError):
pass
def retry(max_retries=10, timeout=10, incremental=False):
"""Decorator to retry web requests in case of failure.
This decorator must be applied to all http requests. Example::
@retryer(max_retries=100, timeout=15)
def handle_my_custom_request(json):
request = requests.get('https://www.google.com/)
return request.text
:param max_retries: The number of tries after a failed request.
:param timeout: The timeout between requests, do not retry immediatly after a failure so the service or
error can be addressed by the source. Example::
Using the code snippet above you'll get a 15 second delay on the in every retry if the request fails.
:param incremental: The timeout will increase according to the number of retries that have been done.Example::
Using the code snippet above you'll get a 15 second delay on the first retry, 30 in the second and so on,
if the request fails.
"""
def wrap(func):
def inner(*args, **kwargs):
for i in range(1, max_retries + 1):
try:
# Run the decorated function
logger.debug('Running function %s...', func.func_name)
result = func(*args, **kwargs)
except:
# the current timeout until the next try
current_timeout = timeout
# if it's set to incremental should be time * tries
if (incremental):
current_timeout = timeout * i
# log the error and sleep for the time accordingly
logger.error('Request failed (%s), retrying in %s...', func.func_name, current_timeout, exc_info=True)
sleep(current_timeout)
# keep on trying...
continue
else:
# everything went fine return
return result
else:
# this is bad, log and raise
logger.error('We`ve exhausted the number of retries, throwing the exception...', exc_info=True)
raise NetworkError
return inner
return wrap