|
11 | 11 | from typing import Iterator |
12 | 12 |
|
13 | 13 | import requests |
| 14 | +from requests.adapters import HTTPAdapter |
| 15 | +from urllib3.util.retry import Retry |
14 | 16 |
|
15 | 17 | from abstractions import AdoptablePet, PetSource |
16 | 18 | from config import CITY_NAME, CITY_STATE, POSTAL_CODE |
|
21 | 23 | # website; those should never be posted. Add new names here as we encounter them. |
22 | 24 | PLACEHOLDER_NAMES: tuple[str, ...] = ("more dogs soon!",) |
23 | 25 |
|
| 26 | +# The RescueGroups API occasionally times out or returns a transient 5xx. A |
| 27 | +# single hiccup shouldn't fail the whole run, so retry a few times with |
| 28 | +# exponential backoff (0s, 2s, 4s, 8s between attempts). |
| 29 | +RETRY_TOTAL = 4 |
| 30 | +RETRY_BACKOFF_FACTOR = 1 |
| 31 | + |
| 32 | + |
| 33 | +def _session_with_retries() -> requests.Session: |
| 34 | + """Build a requests Session that retries transient errors with backoff.""" |
| 35 | + retry = Retry( |
| 36 | + total=RETRY_TOTAL, |
| 37 | + backoff_factor=RETRY_BACKOFF_FACTOR, |
| 38 | + status_forcelist=(429, 500, 502, 503, 504), |
| 39 | + # We only POST, so POST must be opted in (it isn't retried by default). |
| 40 | + allowed_methods=frozenset({"POST"}), |
| 41 | + raise_on_status=False, |
| 42 | + ) |
| 43 | + session = requests.Session() |
| 44 | + session.mount("https://", HTTPAdapter(max_retries=retry)) |
| 45 | + return session |
| 46 | + |
24 | 47 |
|
25 | 48 | class SourceRescueGroups(PetSource): |
26 | 49 | """ |
@@ -92,7 +115,8 @@ def fetch_pets(self) -> Iterator[AdoptablePet]: |
92 | 115 | f"Fetching {self.species} from RescueGroups within {self.radius_miles} miles of {self.postal_code}" |
93 | 116 | ) |
94 | 117 |
|
95 | | - response = requests.post(url, json=payload, headers=headers, timeout=30) |
| 118 | + session = _session_with_retries() |
| 119 | + response = session.post(url, json=payload, headers=headers, timeout=30) |
96 | 120 | response.raise_for_status() |
97 | 121 |
|
98 | 122 | body = response.json() |
|
0 commit comments