diff --git a/sendsafely/utilities.py b/sendsafely/utilities.py index a7d9a7b..346abb2 100644 --- a/sendsafely/utilities.py +++ b/sendsafely/utilities.py @@ -15,6 +15,8 @@ import json import os import secrets +import sys +import time import requests from .pgpy import PGPMessage, PGPKey @@ -195,7 +197,21 @@ def _upload_file_part_to_s3(encrypted_file_part, url): :param url: The S3 URL we're uploading to :return: The JSON response from S3. """ - return requests.put(url=url, data=encrypted_file_part) + max_attempts = 5 + max_backoff_seconds = 180 + for attempt in range(max_attempts): + try: + return requests.put(url=url, data=encrypted_file_part) + except (requests.exceptions.ConnectionError, requests.exceptions.Timeout, + requests.exceptions.ChunkedEncodingError) as e: + if attempt == max_attempts - 1: + raise + sleep_seconds = min(2 ** attempt, max_backoff_seconds) + sys.stdout.write( + '\nRetrying S3 part upload (attempt {0}/{1}) after {2}: sleeping {3}s\n'.format( + attempt + 2, max_attempts, type(e).__name__, sleep_seconds)) + sys.stdout.flush() + time.sleep(sleep_seconds) def _calculate_package_checksum(package_code, keycode): @@ -333,4 +349,4 @@ def _make_safe_for_urlsafebase64(client_secret): client_secret = client_secret.replace("=", "") client_secret = client_secret.replace("+", "-") client_secret = client_secret.replace("/", "_") - return client_secret \ No newline at end of file + return client_secret