Merge "Add backoff and retry to symbol upload" into emu-master-dev
diff --git a/android/build/python/aemu/upload_symbols.py b/android/build/python/aemu/upload_symbols.py
index bd6bc5c..e1d1e11 100644
--- a/android/build/python/aemu/upload_symbols.py
+++ b/android/build/python/aemu/upload_symbols.py
@@ -13,20 +13,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import json
import os
-import requests
import sys
import time
import urllib
-from absl import app
-from absl import flags
-from absl import logging
+import requests
+from absl import app, flags, logging
+from requests.adapters import HTTPAdapter
+from requests.packages.urllib3.util.retry import Retry
FLAGS = flags.FLAGS
flags.DEFINE_string('environment', 'prod',
@@ -68,6 +66,9 @@
# seconds (more precisely, if no bytes have been received on the underlying socket for timeout seconds).
DEFAULT_TIMEOUT = 30
+ # Number of times we will attempt to make the call, including waiting between calls.
+ MAX_RETRY = 5
+
def __init__(self, environment='prod', api_key=None):
endpoint = SymbolFileServer.API_URL if api_key else SymbolFileServer.CLASSIC_API_URL
self.api_url = endpoint[environment.lower()]
@@ -92,6 +93,21 @@
_, os, arch, dbg_id, dbg_file = info
return os, arch, dbg_id, dbg_file
+ def _exec_request_with_retry(self, oper, url, **kwargs):
+ '''Makes a web request with default timeout, returning the response.
+
+ The request will be tried multiple times, with exponential backoff:
+ sleep 1 * (2 ^ ({number of total retries} - 1))
+ '''
+ retries = Retry(total=SymbolFileServer.MAX_RETRY,
+ backoff_factor=1, status_forcelist=[502, 503, 504])
+ with requests.Session() as s:
+ s.mount('https://', HTTPAdapter(max_retries=retries))
+ s.mount('http://', HTTPAdapter(max_retries=retries))
+
+ return s.request(
+ oper, url, params={'key': self.api_key}, timeout=SymbolFileServer.DEFAULT_TIMEOUT, **kwargs)
+
def _exec_request(self, oper, url, **kwargs):
'''Makes a web request with default timeout, returning the json result.
@@ -103,9 +119,7 @@
Note: If you are using verbose logging it is entirely possible that the subsystem will
write your api key to the logs!
'''
- resp = requests.request(
- oper, url, params={'key': self.api_key}, timeout=SymbolFileServer.DEFAULT_TIMEOUT, **kwargs)
-
+ resp = self._exec_request_with_retry(oper, url, **kwargs)
if resp.status_code > 399:
# Make sure we don't leak secret keys by accident.
resp.url = resp.url.replace(
@@ -174,9 +188,12 @@
def main(args):
# The lower level enging will log individual requests!
- logging.debug("-----------------------------------------------------------")
- logging.debug("- WARNING!! You are likely going to leak your api key --")
- logging.debug("-----------------------------------------------------------")
+ logging.debug(
+ "-----------------------------------------------------------")
+ logging.debug(
+ "- WARNING!! You are likely going to leak your api key --")
+ logging.debug(
+ "-----------------------------------------------------------")
api_key = FLAGS.api_key
if not api_key: