@ -120,9 +120,9 @@ def time_time():
return time . time ( )
def log_retry_and_sleep ( seconds , attempt ):
def log_retry_and_sleep ( seconds , attempt , try_limit ):
LOGGER . info ( ' Will retry in %d seconds ( %d more times)... ' , seconds ,
TRY_LIMIT - attempt - 1 )
try_limit - attempt - 1 )
time_sleep ( seconds )
return seconds * random . uniform ( MIN_BACKOFF , MAX_BACKOFF )
@ -757,7 +757,8 @@ class GceAuthenticator(_Authenticator):
# Retry server error status codes.
LOGGER . warning ( ' Encountered server error ' )
if TRY_LIMIT - i > 1 :
next_delay_sec = log_retry_and_sleep ( next_delay_sec , i )
next_delay_sec = log_retry_and_sleep ( next_delay_sec , i ,
TRY_LIMIT )
return None , None
@classmethod
@ -968,25 +969,27 @@ def CreateHttpConn(host: str,
def ReadHttpResponse ( conn : HttpConn ,
accept_statuses : Container [ int ] = frozenset ( [ 200 ] ) ) :
accept_statuses : Container [ int ] = frozenset ( [ 200 ] ) ,
max_tries = TRY_LIMIT ) :
""" Reads an HTTP response from a connection into a string buffer.
Args :
conn : An Http object created by CreateHttpConn above .
accept_statuses : Treat any of these statuses as success . Default : [ 200 ]
Common additions include 204 , 400 , and 404.
max_tries : The maximum number of times the request should be attempted .
Returns :
A string buffer containing the connection ' s reply.
"""
response = contents = None
sleep_time = SLEEP_TIME
for idx in range ( TRY_LIMIT ) :
for idx in range ( max_tries ) :
before_response = time . time ( )
try :
response , contents = conn . request ( * * conn . req_params )
except socket . timeout :
if idx < TRY_LIMIT - 1 :
sleep_time = log_retry_and_sleep ( sleep_time , idx )
if idx < max_tries - 1 :
sleep_time = log_retry_and_sleep ( sleep_time , idx , max_tries )
continue
raise
contents = contents . decode ( ' utf-8 ' , ' replace ' )
@ -1024,8 +1027,8 @@ def ReadHttpResponse(conn: HttpConn,
conn . req_params [ ' uri ' ] , http_version , http_version , response . status ,
response . reason , contents )
if idx < TRY_LIMIT - 1 :
sleep_time = log_retry_and_sleep ( sleep_time , idx )
if idx < max_tries - 1 :
sleep_time = log_retry_and_sleep ( sleep_time , idx , max_tries )
# end of retries loop
# Help the type checker a bit here - it can't figure out the `except` logic
@ -1053,10 +1056,11 @@ def ReadHttpResponse(conn: HttpConn,
raise GerritError ( response . status , reason )
def ReadHttpJsonResponse (
conn , accept_statuses : Container [ int ] = frozenset ( [ 200 ] ) ) - > dict :
def ReadHttpJsonResponse ( conn ,
accept_statuses : Container [ int ] = frozenset ( [ 200 ] ) ,
max_tries = TRY_LIMIT ) - > dict :
""" Parses an https response as json. """
fh = ReadHttpResponse ( conn , accept_statuses )
fh = ReadHttpResponse ( conn , accept_statuses , max_tries )
# The first line of the response should always be: )]}'
s = fh . readline ( )
if s and s . rstrip ( ) != " )]} ' " :
@ -1331,7 +1335,10 @@ def RebaseChange(host, change, base=None):
path = f ' changes/ { change } /rebase '
body = { ' base ' : base } if base else { }
conn = CreateHttpConn ( host , path , reqtype = ' POST ' , body = body )
return ReadHttpJsonResponse ( conn )
# If a rebase fails due to a merge conflict, Gerrit returns 409. Retrying
# more than once probably won't help since the merge conflict will still
# exist.
return ReadHttpJsonResponse ( conn , max_tries = 2 )
def SubmitChange ( host , change ) :