Skip to content

Commit ea9d165

Browse files
committed
Add max_retry_time to the client options
A client may define a max_retries and max_retry_time. Setting only max_retry=N means that the client will retry N times, no matter the time it takes. Signed-off-by: lsenta <laurent.senta@gmail.com>
1 parent d370178 commit ea9d165

File tree

1 file changed

+51
-11
lines changed

1 file changed

+51
-11
lines changed

hubstorage/client.py

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,36 @@ class HubstorageClient(object):
4545
DEFAULT_ENDPOINT = 'http://storage.scrapinghub.com/'
4646
USERAGENT = 'python-hubstorage/{0}'.format(__version__)
4747

48-
DEFAULT_TIMEOUT = 60.0
49-
RETRY_EXPONENTIAL_BACKOFF_MS = 500
50-
RETRY_JITTER_MS = 500
48+
DEFAULT_CONNECTION_TIMEOUT_S = 60.0
49+
RETRY_DEFAUT_MAX_RETRY_TIME_S = 60.0
5150

52-
def __init__(self, auth=None, endpoint=None, connection_timeout=None,
53-
max_retries=3):
51+
RETRY_DEFAULT_MAX_RETRIES = 3
52+
RETRY_DEFAULT_JITTER_MS = 500
53+
RETRY_DEFAULT_EXPONENTIAL_BACKOFF_MS = 500
54+
55+
def __init__(self, auth=None, endpoint=None, connection_timeout=None, max_retries=None, max_retry_time=None):
56+
"""
57+
Note:
58+
max_retries and max_retry_time change how the client attempt to retry failing requests that are
59+
idempotent (safe to execute multiple time).
60+
61+
HubstorageClient(max_retries=3) will retry requests 3 times, no matter the time it takes.
62+
Use max_retry_time if you want to bound the time spent in retrying.
63+
64+
By default, requests are retried at most 3 times, during 60 seconds.
65+
66+
Args:
67+
auth (str): The client authentication token
68+
endpoint (str): The API root address
69+
connection_timeout (int): The connection timeout for a _single request_
70+
max_retries (int): The number of time idempotent requests may be retried
71+
max_retry_time (int): The time, in seconds, during which the client can retry a request
72+
"""
5473
self.auth = xauth(auth)
5574
self.endpoint = endpoint or self.DEFAULT_ENDPOINT
56-
self.connection_timeout = connection_timeout or self.DEFAULT_TIMEOUT
75+
self.connection_timeout = connection_timeout or self.DEFAULT_CONNECTION_TIMEOUT_S
5776
self.session = self._create_session()
58-
self.retrier = self._create_retrier(max_retries, self.RETRY_EXPONENTIAL_BACKOFF_MS, self.RETRY_JITTER_MS)
77+
self.retrier = self._create_retrier(max_retries, max_retry_time)
5978
self.jobq = JobQ(self, None)
6079
self.projects = Projects(self, None)
6180
self.root = ResourceType(self, None)
@@ -81,11 +100,32 @@ def invoke_request():
81100
else:
82101
return invoke_request()
83102

84-
def _create_retrier(self, max_retries, exponential_backoff, jitter):
85-
return Retrying(stop_max_attempt_number=max_retries + 1,
103+
def _create_retrier(self, max_retries, max_retry_time):
104+
"""
105+
Create the Retrier object used to process idempotent client requests.
106+
107+
If only max_retries is set, the default max_retry_time is ignored.
108+
109+
Args:
110+
max_retries (int): the number of retries to be attempted
111+
max_retry_time (int): the number of time, in seconds, to retry for.
112+
Returns:
113+
A Retrying instance, that implements a call(func) method.
114+
"""
115+
116+
# Client sets max_retries only
117+
if max_retries is not None and max_retry_time is None:
118+
stop_max_delay = None
119+
stop_max_attempt_number = max_retries + 1
120+
else:
121+
stop_max_delay = (max_retry_time or self.RETRY_DEFAUT_MAX_RETRY_TIME_S) * 1000.0
122+
stop_max_attempt_number = (max_retries or self.RETRY_DEFAULT_MAX_RETRIES) + 1
123+
124+
return Retrying(stop_max_attempt_number=stop_max_attempt_number,
125+
stop_max_delay=stop_max_delay,
86126
retry_on_exception=_hc_retry_on_exception,
87-
wait_exponential_multiplier=exponential_backoff,
88-
wait_jitter_max=jitter)
127+
wait_exponential_multiplier=self.RETRY_DEFAULT_EXPONENTIAL_BACKOFF_MS,
128+
wait_jitter_max=self.RETRY_DEFAULT_JITTER_MS)
89129

90130
def _create_session(self):
91131
s = session()

0 commit comments

Comments
 (0)