Add transient-network retry with exponential backoff

- bls_client/retry.py: with_retries() retries timeouts/connection drops and
  429/5xx with exponential backoff; honors Retry-After; never retries 4xx or
  BLSQuotaError (those won't fix themselves)
- BLSClient(retries=2, backoff=0.5) wraps the data POST and discovery GETs;
  qcew CSV fetch wrapped too. retries=0 disables.
- tests/test_retry.py: 6 offline tests (injectable sleep, no real delays)
- README: retry behavior documented; drop the now-resolved limitation

Offline suite 125 passing; live smoke green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 10:49:18 -04:00
parent 9e2c55c568
commit 0d0d6dabe2
5 changed files with 188 additions and 8 deletions

View File

@ -21,6 +21,8 @@ import io
import requests
from .retry import with_retries
QCEW_BASE = "https://data.bls.gov/cew/data/api"
_HEADERS = {"User-Agent": "bls-data-library (https://gitea.doesworks.net/giteaadmin/bls-data)"}
@ -35,8 +37,9 @@ OWNERSHIP = {
}
def _fetch_csv(url: str) -> list[dict]:
r = requests.get(url, timeout=60, headers=_HEADERS)
def _fetch_csv(url: str, retries=2, backoff=0.5) -> list[dict]:
r = with_retries(lambda: requests.get(url, timeout=60, headers=_HEADERS),
retries=retries, backoff=backoff)
r.raise_for_status()
return parse_csv(r.text)