fix(usage): honor 429 Retry-After to stop self-sustaining rate-limit loop

The Claude usage poller retried /api/oauth/usage every 60s, but the endpoint
returns 429 with a longer Retry-After window (~93s). Retrying mid-cooldown
re-tripped the limit so the 429s never cleared and usage data never populated.

Record a cooldownUntil from the 429 Retry-After header (5min fallback when
absent) and skip the API until it closes; cleared on success. Dashboard now
shows a "429" indicator instead of a stale value when rate-limited.

Adds regression tests proving the cooldown outlasts the 60s throttle and
releases once the window passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-20 20:55:35 +09:00
parent f9b1e74838
commit 2be6c8db8d
5 changed files with 304 additions and 30 deletions

View File

@@ -480,6 +480,13 @@ export function renderUsageTable(
const renderRows = (rows: UsageRow[]) => {
for (const row of rows) {
if (row.error) {
// Live error (e.g. 429) — show the indicator in both columns instead
// of a bar or a stale value.
const cell = row.error.padEnd(6);
lines.push(`${padName(row.name)}${cell} ${cell}`);
continue;
}
const h5 =
row.h5pct >= 0
? `${bar(row.h5pct)}${String(row.h5pct).padStart(3)}%`