mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
fix(subscription): raise default OAuth usage poll interval to 300s
The Anthropic subscription window tracker polled GET /api/oauth/usage every 10s by default and kept polling even when the proxy was idle (via the cached OAuth token in ~/.claude/.credentials.json). On Pro accounts this blew through Anthropic's metadata rate limit within minutes and produced a steady stream of 429s. Raise the default interval to 300s, raise the upper cap to 3600s, and expose --subscription-poll-interval / --no-subscription-tracking CLI flags (with matching HEADROOM_SUBSCRIPTION_POLL_INTERVAL and HEADROOM_NO_SUBSCRIPTION_TRACKING env vars) so users can tune further or turn the poller off entirely. Fixes #242 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1b70e5c1b0
commit
a1d9832e27
3 changed files with 30 additions and 4 deletions
|
|
@ -57,6 +57,26 @@ from .main import main
|
|||
@click.option("--no-optimize", is_flag=True, help="Disable optimization (passthrough mode)")
|
||||
@click.option("--no-cache", is_flag=True, help="Disable semantic caching")
|
||||
@click.option("--no-rate-limit", is_flag=True, help="Disable rate limiting")
|
||||
@click.option(
|
||||
"--no-subscription-tracking",
|
||||
is_flag=True,
|
||||
envvar="HEADROOM_NO_SUBSCRIPTION_TRACKING",
|
||||
help=(
|
||||
"Disable the Anthropic Claude Code subscription usage poller "
|
||||
"(GET /api/oauth/usage). Env: HEADROOM_NO_SUBSCRIPTION_TRACKING."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--subscription-poll-interval",
|
||||
type=int,
|
||||
default=None,
|
||||
envvar="HEADROOM_SUBSCRIPTION_POLL_INTERVAL",
|
||||
help=(
|
||||
"Seconds between Anthropic subscription usage polls (1–3600, default 300). "
|
||||
"Lower values give fresher /stats but risk 429s from Anthropic. "
|
||||
"Env: HEADROOM_SUBSCRIPTION_POLL_INTERVAL."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--retry-max-attempts",
|
||||
type=int,
|
||||
|
|
@ -254,6 +274,8 @@ def proxy(
|
|||
no_optimize: bool,
|
||||
no_cache: bool,
|
||||
no_rate_limit: bool,
|
||||
no_subscription_tracking: bool,
|
||||
subscription_poll_interval: int | None,
|
||||
retry_max_attempts: int | None,
|
||||
connect_timeout_seconds: int | None,
|
||||
anthropic_pre_upstream_concurrency: int | None,
|
||||
|
|
@ -381,6 +403,10 @@ def proxy(
|
|||
optimize=not no_optimize,
|
||||
cache_enabled=not no_cache,
|
||||
rate_limit_enabled=not no_rate_limit,
|
||||
subscription_tracking_enabled=not no_subscription_tracking,
|
||||
subscription_poll_interval_s=(
|
||||
subscription_poll_interval if subscription_poll_interval is not None else 300
|
||||
),
|
||||
retry_max_attempts=retry_max_attempts if retry_max_attempts is not None else 3,
|
||||
connect_timeout_seconds=connect_timeout_seconds
|
||||
if connect_timeout_seconds is not None
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class ProxyConfig:
|
|||
|
||||
# Subscription Window Tracking (Anthropic OAuth accounts)
|
||||
subscription_tracking_enabled: bool = True
|
||||
subscription_poll_interval_s: int = 10
|
||||
subscription_poll_interval_s: int = 300
|
||||
subscription_active_window_s: int = 60
|
||||
|
||||
# Stateless mode — disable all filesystem writes for read-only / container deployments
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ from headroom.subscription.models import (
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_DEFAULT_POLL_INTERVAL_S = 10
|
||||
_DEFAULT_POLL_INTERVAL_S = 300
|
||||
_DEFAULT_ACTIVE_WINDOW_S = 60
|
||||
_PERSIST_FILE_ENV = _paths.HEADROOM_SUBSCRIPTION_STATE_PATH_ENV
|
||||
_DEFAULT_PERSIST_DIR = ".headroom"
|
||||
|
|
@ -70,7 +70,7 @@ class SubscriptionTracker(QuotaTracker):
|
|||
alongside the Codex and Copilot trackers.
|
||||
|
||||
Args:
|
||||
poll_interval_s: Seconds between polls while active (1–300).
|
||||
poll_interval_s: Seconds between polls while active (1–3600, default 300).
|
||||
active_window_s: Seconds since last notify_active call that keeps
|
||||
polling alive (default 60 = 1 minute).
|
||||
enabled: Set to ``False`` to disable tracking (mirrors
|
||||
|
|
@ -92,7 +92,7 @@ class SubscriptionTracker(QuotaTracker):
|
|||
client: SubscriptionClient | None = None,
|
||||
) -> None:
|
||||
self._enabled = enabled
|
||||
self._poll_interval_s = max(1, min(poll_interval_s, 300))
|
||||
self._poll_interval_s = max(1, min(poll_interval_s, 3600))
|
||||
self._active_window_s = max(5.0, active_window_s)
|
||||
self._persist_path = persist_path or _get_persist_path()
|
||||
self._client = client or SubscriptionClient()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue