feat: exponential backoff
This commit is contained in:
32
api.py
32
api.py
@@ -30,6 +30,9 @@ from authomatic.adapters import WerkzeugAdapter
|
||||
from authomatic.providers import oauth2
|
||||
from authomatic.providers import PROVIDER_ID_MAP as AUTHOMATIC_PROVIDER_ID_MAP
|
||||
|
||||
import random
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
@@ -294,11 +297,32 @@ def get_valid_access_token(spotify_user_id: str) -> str:
|
||||
# ----------------------------
|
||||
|
||||
def spotify_get(url: str, access_token: str, params: dict | None = None) -> dict:
|
||||
"""GET a Spotify Web API endpoint and return the parsed JSON body."""
|
||||
"""
|
||||
GET a Spotify Web API endpoint and return the parsed JSON body.
|
||||
|
||||
Retries on HTTP 429 and 503 with exponential backoff and optional Retry-After,
|
||||
so brief Spotify rate limits often clear before we surface an error to the app.
|
||||
"""
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
r = requests.get(url, headers=headers, params=params)
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
backoff_sec = 1.0
|
||||
max_attempts = 8
|
||||
params_eff = params
|
||||
for attempt in range(max_attempts):
|
||||
r = requests.get(url, headers=headers, params=params_eff)
|
||||
if r.status_code in (429, 503) and attempt < max_attempts - 1:
|
||||
wait = backoff_sec
|
||||
ra = r.headers.get("Retry-After")
|
||||
if ra:
|
||||
try:
|
||||
wait = max(wait, float(ra))
|
||||
except ValueError:
|
||||
pass
|
||||
wait = min(wait, 120.0)
|
||||
time.sleep(wait + random.random() * 0.25 * wait)
|
||||
backoff_sec = min(backoff_sec * 2.0, 60.0)
|
||||
continue
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
|
||||
def spotify_get_paginated(
|
||||
|
||||
Reference in New Issue
Block a user