Merge pull request #33 from tjarko/fix/429-exponential-backoff

Fix OpenAI 429 rate limiting with exponential backoff
This commit is contained in:
Matt Van Horn
2026-02-20 23:03:01 -08:00
committed by GitHub
2 changed files with 21 additions and 4 deletions
+16 -3
View File
@@ -18,8 +18,8 @@ def log(msg: str):
if DEBUG: if DEBUG:
sys.stderr.write(f"[DEBUG] {msg}\n") sys.stderr.write(f"[DEBUG] {msg}\n")
sys.stderr.flush() sys.stderr.flush()
MAX_RETRIES = 3 MAX_RETRIES = 5
RETRY_DELAY = 1.0 RETRY_DELAY = 2.0
USER_AGENT = "last30days-skill/2.1 (Assistant Skill)" USER_AGENT = "last30days-skill/2.1 (Assistant Skill)"
@@ -92,7 +92,20 @@ def request(
raise last_error raise last_error
if attempt < retries - 1: if attempt < retries - 1:
time.sleep(RETRY_DELAY * (attempt + 1)) if e.code == 429:
# Respect Retry-After header, fall back to exponential backoff
retry_after = e.headers.get("Retry-After") if hasattr(e, 'headers') else None
if retry_after:
try:
delay = float(retry_after)
except ValueError:
delay = RETRY_DELAY * (2 ** attempt) + 1
else:
delay = RETRY_DELAY * (2 ** attempt) + 1 # 2s, 5s, 9s...
log(f"Rate limited (429). Waiting {delay:.1f}s before retry {attempt + 2}/{retries}")
else:
delay = RETRY_DELAY * (2 ** attempt)
time.sleep(delay)
except urllib.error.URLError as e: except urllib.error.URLError as e:
log(f"URL Error: {e.reason}") log(f"URL Error: {e.reason}")
last_error = HTTPError(f"URL Error: {e.reason}") last_error = HTTPError(f"URL Error: {e.reason}")
+5 -1
View File
@@ -8,7 +8,8 @@ from typing import Any, Dict, List, Optional
from . import http from . import http
# Fallback models when the selected model isn't accessible (e.g., org not verified for GPT-5) # Fallback models when the selected model isn't accessible (e.g., org not verified for GPT-5)
MODEL_FALLBACK_ORDER = ["gpt-4.1", "gpt-4o", "gpt-4o-mini"] # Note: gpt-4o-mini does NOT support web_search with filters param, so exclude it
MODEL_FALLBACK_ORDER = ["gpt-4.1", "gpt-4o"]
def _log_error(msg: str): def _log_error(msg: str):
@@ -188,6 +189,9 @@ def search_reddit(
if _is_model_access_error(e): if _is_model_access_error(e):
_log_info(f"Model {current_model} not accessible, trying fallback...") _log_info(f"Model {current_model} not accessible, trying fallback...")
continue continue
if e.status_code == 429:
_log_info(f"Rate limited on {current_model}, trying fallback model...")
continue
# Non-access error, don't retry with different model # Non-access error, don't retry with different model
raise raise