@@ -47,7 +47,6 @@ def random_time(loop_count, min_wait_in_ms) -> float:
4747 """
4848 minimum = math .ceil (2 ** loop_count * min_wait_in_ms )
4949 maximum = math .ceil (2 ** (loop_count + 1 ) * min_wait_in_ms )
50-
5150 return random .randrange (minimum , maximum ) / 1000
5251
5352
@@ -253,11 +252,21 @@ def __call_api(
253252 )
254253 else 0
255254 )
255+ max_wait_in_sec = (
256+ self .configuration .retry_params .max_wait_in_sec
257+ if (
258+ self .configuration .retry_params is not None
259+ and self .configuration .retry_params .max_wait_in_sec is not None
260+ )
261+ else 120
262+ )
256263 if _retry_params is not None :
257264 if _retry_params .max_retry is not None :
258265 max_retry = _retry_params .max_retry
259266 if _retry_params .min_wait_in_ms is not None :
260267 max_retry = _retry_params .min_wait_in_ms
268+ if _retry_params .max_wait_in_sec is not None :
269+ max_wait_in_sec = _retry_params .max_wait_in_sec
261270
262271 _telemetry_attributes = TelemetryAttributes .fromRequest (
263272 user_agent = self .user_agent ,
@@ -300,8 +309,14 @@ def __call_api(
300309 configuration = self .configuration .telemetry ,
301310 )
302311
303- time .sleep (random_time (retry , min_wait_in_ms ))
312+ try :
313+ wait_time_in_sec = self ._parse_retry_after_header (e .header )
314+ except ValueError :
315+ wait_time_in_sec = min (
316+ random_time (retry , min_wait_in_ms ), max_wait_in_sec
317+ )
304318
319+ time .sleep (wait_time_in_sec )
305320 continue
306321 e .body = e .body .decode ("utf-8" )
307322 response_type = response_types_map .get (e .status , None )
@@ -395,6 +410,25 @@ def __call_api(
395410 else :
396411 return (return_data , response_data .status , response_data .headers )
397412
413+ def _parse_retry_after_header (self , headers ) -> int :
414+ retry_after_header = headers .get ("retry-after" )
415+ if not retry_after_header :
416+ raise ValueError ("Retry-After header is not present" )
417+
418+ try :
419+ parsed_http_date = self .__deserialize_datetime (retry_after_header ).replace (
420+ tzinfo = datetime .timezone .utc
421+ )
422+ now = datetime .datetime .now (datetime .timezone .utc )
423+ wait_time_in_sec = (parsed_http_date - now ).total_seconds ()
424+ except ApiException :
425+ wait_time_in_sec = int (retry_after_header )
426+
427+ if wait_time_in_sec > 1800 or wait_time_in_sec < 1 :
428+ raise ValueError ("Retry-After header is invalid" )
429+
430+ return math .ceil (wait_time_in_sec )
431+
398432 def sanitize_for_serialization (self , obj ):
399433 """Builds a JSON POST object.
400434
@@ -825,7 +859,7 @@ def __deserialize_datetime(self, string):
825859 return parse (string )
826860 except ImportError :
827861 return string
828- except ValueError :
862+ except ( TypeError , ValueError ) :
829863 raise rest .ApiException (
830864 status = 0 ,
831865 reason = (f"Failed to parse `{ string } ` as datetime object" ),
0 commit comments