feat(usage): poll the OAuth usage endpoint as fast as its measured rate limit allows
Measured 2026-09-16 against the live endpoint: a clean burst allows exactly 5 requests before a 429, with Retry-After: 300 (a flat 5-req/5-min quota, no ratelimit-* headers on either the 200s or the 429s). Lowered UsagePollIntervalActiveSeconds/UsagePollIntervalIdleSeconds default from 300/900 to 120 each (clamp floor 90, up from 60) — leaves ~2.5 requests of headroom per window for manual refreshes and any other consumer of the same OAuth token, unlike 60s which consumes the whole quota by itself. The quota is a flat per-account limit, not tied to ClaudeDo's own running/idle state, so both keys share the same default now (kept separate for config compatibility). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
committed by
mika kuns
co-authored by
Claude Sonnet 5
parent
9a41bed0f5
commit
50b6b56f87
@@ -46,16 +46,25 @@ public sealed class WorkerConfig
|
||||
|
||||
/// <summary>
|
||||
/// Usage-monitor poll interval while at least one task is Running. Clamped to a minimum
|
||||
/// of 60s on load — the endpoint rate-limits (429) on tighter polling.
|
||||
/// of 90s on load. Measured 2026-09-16 against the live endpoint: a clean burst allows
|
||||
/// exactly 5 requests before a 429, with <c>Retry-After: 300</c> (a flat 5-req/5-min quota,
|
||||
/// no <c>ratelimit-*</c> headers). 120s leaves ~2.5 requests of headroom per 5-minute window
|
||||
/// for manual refreshes and any other consumer of the same OAuth token — 60s consumes the
|
||||
/// whole quota by itself with zero margin, which is what made the old flat-60s cadence 429
|
||||
/// (see commit 2700c3d8). Same default as <see cref="UsagePollIntervalIdleSeconds"/>: the
|
||||
/// quota is a flat per-account limit, not tied to ClaudeDo's own activity, so an active/idle
|
||||
/// split buys nothing safety-wise. The two config keys stay separate for compatibility.
|
||||
/// </summary>
|
||||
[JsonPropertyName("usage_poll_interval_active_seconds")]
|
||||
public int UsagePollIntervalActiveSeconds { get; set; } = 300;
|
||||
public int UsagePollIntervalActiveSeconds { get; set; } = 120;
|
||||
|
||||
/// <summary>
|
||||
/// Usage-monitor poll interval while nothing is running. Clamped to a minimum of 60s on load.
|
||||
/// Usage-monitor poll interval while nothing is running. Clamped to a minimum of 90s on
|
||||
/// load. Same default as <see cref="UsagePollIntervalActiveSeconds"/> — see that doc for the
|
||||
/// measured rate limit this is sized against.
|
||||
/// </summary>
|
||||
[JsonPropertyName("usage_poll_interval_idle_seconds")]
|
||||
public int UsagePollIntervalIdleSeconds { get; set; } = 900;
|
||||
public int UsagePollIntervalIdleSeconds { get; set; } = 120;
|
||||
|
||||
/// <summary>Base URL of the Bandel ticket-system API. Null = ticket integration off entirely.</summary>
|
||||
[JsonPropertyName("ticket_api_base_url")]
|
||||
@@ -88,8 +97,8 @@ public sealed class WorkerConfig
|
||||
cfg.SandboxRoot = Paths.Expand(cfg.SandboxRoot);
|
||||
cfg.LogRoot = Paths.Expand(cfg.LogRoot);
|
||||
cfg.CentralWorktreeRoot = Paths.Expand(cfg.CentralWorktreeRoot);
|
||||
cfg.UsagePollIntervalActiveSeconds = Math.Max(60, cfg.UsagePollIntervalActiveSeconds);
|
||||
cfg.UsagePollIntervalIdleSeconds = Math.Max(60, cfg.UsagePollIntervalIdleSeconds);
|
||||
cfg.UsagePollIntervalActiveSeconds = Math.Max(90, cfg.UsagePollIntervalActiveSeconds);
|
||||
cfg.UsagePollIntervalIdleSeconds = Math.Max(90, cfg.UsagePollIntervalIdleSeconds);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user