Repository navigation
fix(server): proxied usage limits take their reset from the configured hub #34913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ffe1e81
719fd52
e93e1d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ import { | |
| UsageLimitSourceError, | ||
| type UsageLimitSourceConsumeResetCreditInput, | ||
| type ProviderConsumeResetCreditResult, | ||
| type ProviderDriverKind, | ||
| type ServerSettings, | ||
| UsageLimitSourceConfig, | ||
| settingsSecretLiteral, | ||
|
|
@@ -40,6 +41,27 @@ export class UsageLimitSources extends Context.Service< | |
| } | ||
| >()("t3/usage/UsageLimitSources") {} | ||
|
|
||
| /** When a hub has exhausted every pooled account for `driver`, the earliest moment one refills. */ | ||
| export function exhaustedPoolRefillAt( | ||
| sources: ReadonlyArray<UsageLimitSourceSnapshot>, | ||
| driver: ProviderDriverKind, | ||
| now: number, | ||
| ): string | null { | ||
| let earliest: number | null = null; | ||
| for (const account of sources.flatMap((source) => source.accounts)) { | ||
| if (account.driver !== driver) continue; | ||
| const refills = account.usageLimits.windows | ||
| .filter((window) => window.usedPercent >= 100 && window.resetsAt !== undefined) | ||
| .map((window) => Date.parse(window.resetsAt!)) | ||
| .filter((at) => at > now); | ||
|
Comment on lines
+54
to
+56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Treat an exhausted window without a usable reset as an unknown refill time. For each account, the helper drops exhausted windows that have no reset. The remaining resets are used as the account refill time. An account can stay blocked by that dropped window after the known reset. The returned time can then be earlier than the account can serve, so a retry can run before the blocking window resets and fail again. The helper already treats an account with an unknown refill time as having no pool reset. Apply the same rule to an exhausted window with no usable reset. Windows whose reset has already passed still stop blocking and are still ignored. Suggested fix
|
||
| // An account with no exhausted window may still serve, so the pool has no reset. | ||
| if (refills.length === 0) return null; | ||
| const refill = Math.max(...refills); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 High A failed Haiku request can receive the five-day reset for an exhausted Opus-only weekly quota, delaying automatic recovery even though Haiku's session quota resets in two hours. 🚀 Reply "fix it for me" or copy this AI Prompt for your agent: |
||
| if (earliest === null || refill < earliest) earliest = refill; | ||
| } | ||
| return earliest === null ? null : DateTime.formatIso(DateTime.makeUnsafe(earliest)); | ||
| } | ||
|
|
||
| function sourceLabel(id: string, config: UsageLimitSourceConfig): string { | ||
| if (config.label) return config.label; | ||
| const fallback = id.trim() || "Usage limit source"; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reset lookup mixes accounts from every configured hub.
exhaustedPoolRefillAtis called with the full snapshot and does not preserve hub identity. For a proxiedusage_limitfailure, the reset can come from an unrelated hub:resetAtthan the hub that served the request.null, so a valid reset from the serving hub is dropped.Scoping the lookup to the associated hub requires an instance-to-source association. None exists in the current provider or settings data, so this change does not fix the behavior. Treat this as a known gap that remains until that association is added.