Source code for tierproxy.retry
from __future__ import annotations
import random
from dataclasses import dataclass, field
[docs]
@dataclass(frozen=True)
class RetryPolicy:
max_retries: int = 3
initial_delay_seconds: float = 0.5
max_delay_seconds: float = 30.0
multiplier: float = 2.0
jitter: float = 0.25
retry_on_status: frozenset[int] = field(
default_factory=lambda: frozenset({408, 429, 500, 502, 503, 504})
)
retry_on_methods: frozenset[str] = field(
default_factory=lambda: frozenset({"GET", "HEAD", "OPTIONS", "PUT", "DELETE"})
)
def should_retry(
self,
attempt: int,
method: str,
status_code: int | None,
had_network_error: bool,
is_idempotent: bool,
) -> bool:
if attempt >= self.max_retries:
return False
if had_network_error:
return method in self.retry_on_methods or is_idempotent
if status_code is None:
return False
if status_code == 429:
return True
if status_code in self.retry_on_status:
return method in self.retry_on_methods or is_idempotent
return False
def delay(self, attempt: int, retry_after: float | None = None) -> float:
if retry_after is not None:
return min(retry_after, self.max_delay_seconds)
base = min(
self.initial_delay_seconds * (self.multiplier**attempt),
self.max_delay_seconds,
)
jr = base * self.jitter
return base + random.uniform(-jr, jr) # noqa: S311