Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: infra_libs/httplib2_utils.py

Issue 2153483002: RetriableHttp to sleep between retries (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import collections 5 import collections
6 import copy 6 import copy
7 import json 7 import json
8 import logging 8 import logging
9 import os 9 import os
10 import re 10 import re
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 158
159 if http_identifier: 159 if http_identifier:
160 http = InstrumentedHttp(http_identifier, timeout=timeout) 160 http = InstrumentedHttp(http_identifier, timeout=timeout)
161 else: 161 else:
162 http = httplib2.Http(timeout=timeout) 162 http = httplib2.Http(timeout=timeout)
163 return creds.authorize(http) 163 return creds.authorize(http)
164 164
165 class RetriableHttp(object): 165 class RetriableHttp(object):
166 """A httplib2.Http object that retries on failure.""" 166 """A httplib2.Http object that retries on failure."""
167 167
168 def __init__(self, http, max_tries=5, retrying_statuses_fn=None): 168 def __init__(self, http, max_tries=5, backoff_time=1,
169 retrying_statuses_fn=None):
169 """ 170 """
170 Args: 171 Args:
171 http: an httplib2.Http instance 172 http: an httplib2.Http instance
172 max_tries: a number of maximum tries 173 max_tries: a number of maximum tries
174 backoff_time: a number of seconds to sleep between retries
173 retrying_statuses_fn: a function that returns True if a given status 175 retrying_statuses_fn: a function that returns True if a given status
174 should be retried 176 should be retried
175 """ 177 """
176 self._http = http 178 self._http = http
177 self._max_tries = max_tries 179 self._max_tries = max_tries
180 self._backoff_time = backoff_time
178 self._retrying_statuses_fn = retrying_statuses_fn or \ 181 self._retrying_statuses_fn = retrying_statuses_fn or \
179 set(range(500,599)).__contains__ 182 set(range(500,599)).__contains__
180 183
181 def request(self, uri, method='GET', body=None, *args, **kwargs): 184 def request(self, uri, method='GET', body=None, *args, **kwargs):
182 for i in range(1, self._max_tries + 1): 185 for i in range(1, self._max_tries + 1):
183 try: 186 try:
184 response, content = self._http.request(uri, method, body, *args, 187 response, content = self._http.request(uri, method, body, *args,
185 **kwargs) 188 **kwargs)
186 189
187 if self._retrying_statuses_fn(response.status): 190 if self._retrying_statuses_fn(response.status):
188 logging.info('RetriableHttp: attempt %d receiving status %d, %s', 191 logging.info('RetriableHttp: attempt %d receiving status %d, %s',
189 i, response.status, 192 i, response.status,
190 'final attempt' if i == self._max_tries else \ 193 'final attempt' if i == self._max_tries else \
191 'will retry') 194 'will retry')
192 else: 195 else:
193 break 196 break
194 except (ValueError, errors.Error, 197 except (ValueError, errors.Error,
195 socket.timeout, socket.error, socket.herror, socket.gaierror, 198 socket.timeout, socket.error, socket.herror, socket.gaierror,
196 httplib2.HttpLib2Error) as error: 199 httplib2.HttpLib2Error) as error:
197 logging.info('RetriableHttp: attempt %d received exception: %s, %s', 200 logging.info('RetriableHttp: attempt %d received exception: %s, %s',
198 i, error, 'final attempt' if i == self._max_tries else \ 201 i, error, 'final attempt' if i == self._max_tries else \
199 'will retry') 202 'will retry')
200 if i == self._max_tries: 203 if i == self._max_tries:
201 raise 204 raise
205 time.sleep(self._backoff_time)
202 206
203 return response, content 207 return response, content
204 208
205 def __getattr__(self, name): 209 def __getattr__(self, name):
206 return getattr(self._http, name) 210 return getattr(self._http, name)
207 211
208 def __setattr__(self, name, value): 212 def __setattr__(self, name, value):
209 if name in ('request', '_http', '_max_tries', '_retrying_statuses_fn'): 213 if name in ('request', '_http', '_max_tries', '_backoff_time',
214 '_retrying_statuses_fn'):
210 self.__dict__[name] = value 215 self.__dict__[name] = value
211 else: 216 else:
212 setattr(self._http, name, value) 217 setattr(self._http, name, value)
213 218
214 class InstrumentedHttp(httplib2.Http): 219 class InstrumentedHttp(httplib2.Http):
215 """A httplib2.Http object that reports ts_mon metrics about its requests.""" 220 """A httplib2.Http object that reports ts_mon metrics about its requests."""
216 221
217 def __init__(self, name, time_fn=time.time, timeout=DEFAULT_TIMEOUT, 222 def __init__(self, name, time_fn=time.time, timeout=DEFAULT_TIMEOUT,
218 **kwargs): 223 **kwargs):
219 """ 224 """
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 self.requests_made.append(self.HttpCall(uri, method, body, headers)) 311 self.requests_made.append(self.HttpCall(uri, method, body, headers))
307 headers = None 312 headers = None
308 body = None 313 body = None
309 for candidate in self._uris: 314 for candidate in self._uris:
310 if candidate[0].match(uri): 315 if candidate[0].match(uri):
311 _, headers, body = candidate 316 _, headers, body = candidate
312 break 317 break
313 if not headers: 318 if not headers:
314 raise AssertionError("Unexpected request to %s" % uri) 319 raise AssertionError("Unexpected request to %s" % uri)
315 return httplib2.Response(headers), body 320 return httplib2.Response(headers), body
OLDNEW
« no previous file with comments | « no previous file | infra_libs/test/httplib2_utils_test.py » ('j') | infra_libs/test/httplib2_utils_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698