fix: detect stale usage data after account rate-limit/quota reset#272
fix: detect stale usage data after account rate-limit/quota reset#272XavLimSG wants to merge 1 commit intoSoju06:mainfrom
Conversation
When an account's usage window resets (e.g. daily/weekly limit rollover), the load balancer could continue treating the account as exhausted because: 1. `_latest_usage_is_fresh()` only checked record age, not whether the `reset_at` timestamp had passed — stale 100% data persisted until the next refresh interval even though the upstream limit had already reset. 2. `_state_from_account()` passed stale 100% usage into the balancer and sort keys even when `reset_at` was in the past, causing the account to be blocked or deprioritised. 3. `select_account()` cleared the blocked status when `reset_at` expired but did not reset `used_percent` (RATE_LIMITED) or `secondary_used_percent` (QUOTA_EXCEEDED), so the account remained last in usage-weighted selection. This commit fixes all three layers: - Freshness check now returns false when `reset_at` has passed, forcing an immediate re-fetch from the upstream API. - A new `_account_needs_post_reset_refresh()` helper forces refresh even when primary data looks fresh but the account's persisted reset time has expired (covers secondary-only resets). - `_state_from_account()` zeros out stale exhausted percentages when the window has rolled over. - `select_account()` resets both `used_percent` and `secondary_used_percent` when clearing expired statuses. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1ad7f43c5e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # Still force a refresh when the account is blocked with an | ||
| # expired reset — the fresh primary entry does not capture | ||
| # that the upstream window has turned over. | ||
| if not _account_needs_post_reset_refresh(account, now): | ||
| continue |
There was a problem hiding this comment.
Bypass stale gate when forcing post-reset usage refresh
This branch intends to force a refresh for blocked accounts whose reset_at has already expired, but it still falls through to _refresh_account_if_stale(), which re-checks primary freshness and can return early without fetching. In the secondary-window rollover scenario (account remains QUOTA_EXCEEDED/RATE_LIMITED, primary row still fresh), the new _account_needs_post_reset_refresh path does not actually trigger an upstream refresh, so recovery is delayed until the normal primary interval expires.
Useful? React with 👍 / 👎.
Summary
Fixes an issue where the load balancer doesn't update when user account usage windows reset (daily/weekly limit rollover). Accounts could remain blocked or deprioritised indefinitely after their limits refresh upstream.
Root causes fixed:
_latest_usage_is_fresh()ignored reset boundaries — the freshness check only compared record age against the refresh interval, so stale 100% usage data persisted even afterreset_athad passed. Now returnsfalsewhen the window has rolled over, forcing an immediate re-fetch._state_from_account()passed stale exhausted data into the balancer — when the last recorded sample showed 100% usage but thereset_atwas already in the past, the account was still blocked or sorted last. Now zeros out stale percentages when the window has rolled over.select_account()didn't fully clear usage on status recovery —RATE_LIMITEDrecovery didn't resetused_percent, andQUOTA_EXCEEDEDrecovery didn't resetsecondary_used_percent, so recovered accounts were deprioritised in usage-weighted selection._account_needs_post_reset_refresh()— forces a usage refresh when an account's persistedreset_athas expired but the primary usage entry still looks fresh (covers secondary-only resets).Files changed
app/modules/usage/updater.py_latest_usage_is_fresh()now checksreset_at; new_account_needs_post_reset_refresh()helper;refresh_accounts()uses itapp/modules/proxy/load_balancer.py_state_from_account()zeros stale 100% data when reset_at is pastapp/core/balancer/logic.pyselect_account()resetsused_percentandsecondary_used_percenton status cleartests/unit/test_usage_updater.pytests/unit/test_load_balancer.pyTest plan
🤖 Generated with Claude Code