Check if error is retryable and sleep, or re-raise.
(
self,
error: InstanceError | TimeoutError,
command: str,
elapsed_ms: float,
retry_initial_ms: int,
retry_max_ms: int,
retry_max_time_ms: int,
attempt: int,
)
| 259 | attempt += 1 |
| 260 | |
| 261 | def _maybe_retry( |
| 262 | self, |
| 263 | error: InstanceError | TimeoutError, |
| 264 | command: str, |
| 265 | elapsed_ms: float, |
| 266 | retry_initial_ms: int, |
| 267 | retry_max_ms: int, |
| 268 | retry_max_time_ms: int, |
| 269 | attempt: int, |
| 270 | ) -> None: |
| 271 | """Check if error is retryable and sleep, or re-raise.""" |
| 272 | error_code = getattr(error, "code", "UNKNOWN") |
| 273 | if error_code not in self._RETRYABLE_CODES: |
| 274 | raise error |
| 275 | |
| 276 | backoff_ms = min(retry_initial_ms * (2**attempt), retry_max_ms) |
| 277 | if elapsed_ms + backoff_ms >= retry_max_time_ms: |
| 278 | raise TimeoutError( |
| 279 | f"Max retry time would be exceeded for '{command}' " |
| 280 | f"(elapsed: {elapsed_ms:.0f}ms, next backoff: {backoff_ms}ms)", |
| 281 | "RETRY_TIMEOUT", |
| 282 | ) from error |
| 283 | |
| 284 | if self.on_retry: |
| 285 | self.on_retry(error_code, error.message, attempt + 1, backoff_ms) |
| 286 | time.sleep(backoff_ms / 1000) |
| 287 | |
| 288 | def _send_request_once( |
| 289 | self, |
no test coverage detected