Files
2026-07-13 12:23:54 +08:00

30 lines
1.0 KiB
Python

import tenacity
import traceback
import logging
import requests
def after_func(retry_state: tenacity.RetryCallState) -> None:
if retry_state.outcome.failed:
exc = retry_state.outcome.exception()
logging.warning(f"Retrying {retry_state.fn.__name__} due to {repr(exc)} (Attempt {retry_state.attempt_number})")
logging.debug(traceback.format_exception(type(exc), exc, exc.__traceback__))
def is_retryable_download_error(exc: BaseException) -> bool:
"""Network errors and 5xx responses are retryable; other HTTP errors (expired
or invalid URLs, auth failures) will never succeed and must fail fast."""
if isinstance(exc, requests.HTTPError):
response = exc.response
return response is None or response.status_code >= 500
return isinstance(exc, requests.RequestException)
download_retry = tenacity.retry(
stop=tenacity.stop_after_attempt(3),
wait=tenacity.wait_exponential(multiplier=1, max=10),
retry=tenacity.retry_if_exception(is_retryable_download_error),
after=after_func,
reraise=True,
)