tts-voice-creator-clone-and.../core/retry.py

41 lines
1.6 KiB
Python

"""Small, bounded retry primitives shared by outbound provider requests."""
from __future__ import annotations
import time
from collections.abc import Callable
import requests
_RETRYABLE_STATUS_CODES = frozenset({408, 425, 429, 500, 502, 503, 504})
def retry_delay(attempt: int, *, base: float = 0.5, cap: float = 8.0) -> float:
"""Return bounded exponential backoff for the zero-based retry attempt."""
return min(float(cap), max(0.0, float(base)) * (2 ** max(0, int(attempt))))
def request_with_retries(method: str, url: str, *, attempts: int = 3,
sleep: Callable[[float], None] | None = None, **kwargs):
"""Make a request, retrying only transient transport/upstream failures.
The final response or exception is returned to the caller unchanged. Any
response discarded before a retry is closed so streaming sockets cannot
accumulate while a provider is cold or rate-limiting.
"""
attempts = max(1, min(int(attempts), 5))
sleep = sleep or time.sleep
last_response = None
for attempt in range(attempts):
try:
response = requests.request(method, url, **kwargs)
last_response = response
if response.status_code not in _RETRYABLE_STATUS_CODES or attempt >= attempts - 1:
return response
response.close()
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
if attempt >= attempts - 1:
raise
if attempt < attempts - 1:
sleep(retry_delay(attempt))
return last_response