Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 credentials_filename, | 155 credentials_filename, |
| 156 scope=scope, | 156 scope=scope, |
| 157 service_accounts_creds_root=service_accounts_creds_root) | 157 service_accounts_creds_root=service_accounts_creds_root) |
| 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(httplib2.Http): | 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, max_tries=5, retrying_statuses_fn=None, **kwargs): | 168 def __init__(self, http, max_tries=5, retrying_statuses_fn=None, **kwargs): |
| 169 """ | 169 """ |
| 170 Args: | 170 Args: |
| 171 http_obj: an httplib2.Http instance | 171 http: an httplib2.Http instance |
| 172 max_tries: a number of maximum tries | 172 max_tries: a number of maximum tries |
| 173 retrying_statuses_fn: a function that returns True if a given status | 173 retrying_statuses_fn: a function that returns True if a given status |
| 174 should be retried | 174 should be retried |
| 175 """ | 175 """ |
| 176 super(RetriableHttp, self).__init__(**kwargs) | 176 super(RetriableHttp, self).__init__(**kwargs) |
|
Sergey Berezin
2016/07/07 22:44:36
nit: kwargs is not used, let's remove it.
Sergey Berezin
2016/07/07 22:45:28
Wait, nevermind - it's fine. I wasn't looking in t
tnn
2016/07/07 22:54:54
We should remove kwargs like you suggested. It doe
| |
| 177 self._http = http | |
| 177 self._max_tries = max_tries | 178 self._max_tries = max_tries |
| 178 self._retrying_statuses_fn = retrying_statuses_fn or \ | 179 self._retrying_statuses_fn = retrying_statuses_fn or \ |
| 179 set(range(500,599)).__contains__ | 180 set(range(500,599)).__contains__ |
| 180 | 181 |
| 181 def request(self, uri, method='GET', body=None, *args, **kwargs): | 182 def request(self, uri, method='GET', body=None, *args, **kwargs): |
| 182 for i in range(1, self._max_tries + 1): | 183 for i in range(1, self._max_tries + 1): |
| 183 try: | 184 try: |
| 184 response, content = super(RetriableHttp, self).request( | 185 response, content = self._http.request(uri, method, body, *args, |
| 185 uri, method, body, *args, **kwargs) | 186 **kwargs) |
| 186 | 187 |
| 187 if self._retrying_statuses_fn(response.status): | 188 if self._retrying_statuses_fn(response.status): |
| 188 logging.info('RetriableHttp: attempt %d receiving status %d, %s', | 189 logging.info('RetriableHttp: attempt %d receiving status %d, %s', |
| 189 i, response.status, | 190 i, response.status, |
| 190 'final attempt' if i == self._max_tries else \ | 191 'final attempt' if i == self._max_tries else \ |
| 191 'will retry') | 192 'will retry') |
| 192 else: | 193 else: |
| 193 break | 194 break |
| 194 except (ValueError, errors.Error, | 195 except (ValueError, errors.Error, |
| 195 socket.timeout, socket.error, socket.herror, socket.gaierror, | 196 socket.timeout, socket.error, socket.herror, socket.gaierror, |
| 196 httplib2.HttpLib2Error) as error: | 197 httplib2.HttpLib2Error) as error: |
| 197 logging.info('RetriableHttp: attempt %d received exception: %s, %s', | 198 logging.info('RetriableHttp: attempt %d received exception: %s, %s', |
| 198 i, error, 'final attempt' if i == self._max_tries else \ | 199 i, error, 'final attempt' if i == self._max_tries else \ |
| 199 'will retry') | 200 'will retry') |
| 200 if i == self._max_tries: | 201 if i == self._max_tries: |
| 201 raise | 202 raise |
| 202 | 203 |
| 203 return response, content | 204 return response, content |
| 204 | 205 |
| 206 def __getattr__(self, name): | |
| 207 return getattr(self._http, name) | |
|
Sergey Berezin
2016/07/07 22:28:53
Let's also add __setattr__() here, e.g.:
def __se
tnn
2016/07/07 22:54:54
Done.
| |
| 205 | 208 |
| 206 class InstrumentedHttp(httplib2.Http): | 209 class InstrumentedHttp(httplib2.Http): |
| 207 """A httplib2.Http object that reports ts_mon metrics about its requests.""" | 210 """A httplib2.Http object that reports ts_mon metrics about its requests.""" |
| 208 | 211 |
| 209 def __init__(self, name, time_fn=time.time, timeout=DEFAULT_TIMEOUT, | 212 def __init__(self, name, time_fn=time.time, timeout=DEFAULT_TIMEOUT, |
| 210 **kwargs): | 213 **kwargs): |
| 211 """ | 214 """ |
| 212 Args: | 215 Args: |
| 213 name: An identifier for the HTTP requests made by this object. | 216 name: An identifier for the HTTP requests made by this object. |
| 214 time_fn: Function returning the current time in seconds. Use for testing | 217 time_fn: Function returning the current time in seconds. Use for testing |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 self.requests_made.append(self.HttpCall(uri, method, body, headers)) | 301 self.requests_made.append(self.HttpCall(uri, method, body, headers)) |
| 299 headers = None | 302 headers = None |
| 300 body = None | 303 body = None |
| 301 for candidate in self._uris: | 304 for candidate in self._uris: |
| 302 if candidate[0].match(uri): | 305 if candidate[0].match(uri): |
| 303 _, headers, body = candidate | 306 _, headers, body = candidate |
| 304 break | 307 break |
| 305 if not headers: | 308 if not headers: |
| 306 raise AssertionError("Unexpected request to %s" % uri) | 309 raise AssertionError("Unexpected request to %s" % uri) |
| 307 return httplib2.Response(headers), body | 310 return httplib2.Response(headers), body |
| OLD | NEW |