Index: chrome/common/extensions/docs/server2/appengine_url_fetcher.py |
diff --git a/chrome/common/extensions/docs/server2/appengine_url_fetcher.py b/chrome/common/extensions/docs/server2/appengine_url_fetcher.py |
index c9a94b0632478a422a5039964f834bc6d6b970be..8ed0494b3d2f4832e1c8ce181c83a3fc2bb5fb2c 100644 |
--- a/chrome/common/extensions/docs/server2/appengine_url_fetcher.py |
+++ b/chrome/common/extensions/docs/server2/appengine_url_fetcher.py |
@@ -3,13 +3,19 @@ |
# found in the LICENSE file. |
import base64 |
+import logging |
import posixpath |
+import time |
from appengine_wrappers import urlfetch |
from environment import GetAppVersion |
from future import Future |
+_MAX_RETRIES = 5 |
+_RETRY_DELAY_SECONDS = 30 |
+ |
+ |
def _MakeHeaders(username, password, access_token): |
headers = { |
'User-Agent': 'Chromium docserver %s' % GetAppVersion(), |
@@ -30,6 +36,7 @@ class AppEngineUrlFetcher(object): |
def __init__(self, base_path=None): |
assert base_path is None or not base_path.endswith('/'), base_path |
self._base_path = base_path |
+ self._retries_left = _MAX_RETRIES |
def Fetch(self, url, username=None, password=None, access_token=None): |
"""Fetches a file synchronously. |
@@ -43,13 +50,25 @@ class AppEngineUrlFetcher(object): |
def FetchAsync(self, url, username=None, password=None, access_token=None): |
"""Fetches a file asynchronously, and returns a Future with the result. |
""" |
+ def process_result(result): |
+ if result.status_code == 429: |
+ if self._retries_left == 0: |
+ logging.error('Still throttled. Giving up.') |
+ return result |
+ self._retries_left -= 1 |
+ logging.info('Throttled. Trying again in %s seconds.' % |
+ _RETRY_DELAY_SECONDS) |
+ time.sleep(_RETRY_DELAY_SECONDS) |
+ return self.FetchAsync(url, username, password, access_token).Get() |
+ return result |
+ |
rpc = urlfetch.create_rpc(deadline=20) |
urlfetch.make_fetch_call(rpc, |
self._FromBasePath(url), |
headers=_MakeHeaders(username, |
password, |
access_token)) |
- return Future(callback=lambda: rpc.get_result()) |
+ return Future(callback=lambda: process_result(rpc.get_result())) |
def _FromBasePath(self, url): |
assert not url.startswith('/'), url |