66"""
77
88import logging
9- import random
109from abc import ABC , abstractmethod
1110from typing import Callable , Mapping
1211
1615 Retrying ,
1716 stop_after_attempt ,
1817)
19-
20- RETRYABLE_STATUS_CODES = {408 , 429 , 502 , 503 , 504 }
18+ from uipath .platform .common .retry import (
19+ RETRYABLE_STATUS_CODES ,
20+ exponential_backoff_with_jitter ,
21+ parse_retry_after ,
22+ )
2123
2224
2325class RetryProvider (ABC ):
@@ -89,16 +91,6 @@ def _create_wait_strategy(
8991) -> Callable [[RetryCallState ], float ]:
9092 """Create wait strategy honoring Retry-After header with exponential backoff fallback."""
9193
92- def _parse_retry_after (header_value : str ) -> float | None :
93- """Parse Retry-After header value (durations only, not datetimes)."""
94- try :
95- seconds = float (header_value .strip ())
96- if seconds < 0 :
97- return None
98- return seconds
99- except (ValueError , AttributeError ):
100- return None
101-
10294 def _extract_retry_after_header (exception : BaseException ) -> float | None :
10395 """Extract and parse Retry-After header from exception chain."""
10496 current : BaseException | None = exception
@@ -107,19 +99,12 @@ def _extract_retry_after_header(exception: BaseException) -> float | None:
10799 if headers :
108100 retry_after = headers .get ("retry-after" ) or headers .get ("Retry-After" )
109101 if retry_after :
110- parsed = _parse_retry_after (retry_after )
102+ parsed = parse_retry_after (retry_after )
111103 if parsed is not None :
112104 return parsed
113105 current = current .__cause__
114106 return None
115107
116- def _exponential_backoff (attempt : int , initial : float ) -> float :
117- """Calculate exponential backoff with jitter."""
118- exponent = attempt - 1
119- exponential = initial * (2 ** exponent )
120- jitter = random .uniform (0 , 1.0 )
121- return exponential + jitter
122-
123108 def wait_strategy (retry_state : RetryCallState ) -> float :
124109 """Calculate wait time based on exception and retry state."""
125110 if retry_state .outcome is None :
@@ -137,7 +122,9 @@ def wait_strategy(retry_state: RetryCallState) -> float:
137122 )
138123 return capped_wait
139124
140- exponential_wait = _exponential_backoff (retry_state .attempt_number , initial )
125+ exponential_wait = exponential_backoff_with_jitter (
126+ retry_state .attempt_number , initial
127+ )
141128 capped_wait = min (exponential_wait , max_delay )
142129 if logger :
143130 logger .info (
0 commit comments