Honor Retry-After on HTTP 429 (polite rest, not a failure)
Per Codex's spec — a publisher saying "slow down" shouldn't make a feed look broken, but repeated 429s stay visible via last_success_at / stale-source. * Schema: sources.retry_after_at (nullable) + migration. * feeds.parse_retry_after: delta-seconds OR HTTP-date → UTC stamp; ignores invalid/negative/past; caps at now + MAX_BACKOFF_MINUTES. * fetch_feed raises RateLimited (carrying the parsed time) on a 429. * poll_source: on 429 set retry_after_at + last_error, status='rate_limited', and do NOT increment consecutive_failures; on success clear retry_after_at; non-429 failures unchanged. * due_source_rows requires BOTH the streak backoff elapsed AND retry_after_at passed (i.e. the later of the two). * Admin: source_health returns retry_after_at; status reads "rate-limited · rests until …" rather than "failed/resting". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -295,7 +295,7 @@ def source_health(conn: sqlite3.Connection) -> list[dict]:
|
||||
"""
|
||||
SELECT
|
||||
s.id, s.name, s.default_category AS category, s.active,
|
||||
s.status, s.content_visible,
|
||||
s.status, s.content_visible, s.retry_after_at,
|
||||
s.consecutive_failures AS failures, s.review_flag, s.review_reason,
|
||||
s.poll_interval_minutes AS interval_minutes,
|
||||
s.last_success_at, s.last_error_at, substr(s.last_error, 1, 160) AS last_error,
|
||||
|
||||
Reference in New Issue
Block a user