Skip to content

fix(proxy): prioritize expiring session windows in account routing - #1167

Merged
murdore merged 1 commit into
releasefrom
fix/proxy-session-first-routing
Jul 15, 2026
Merged

murdore merged 1 commit into
releasefrom
fix/proxy-session-first-routing

Conversation

@pdogra1299

@pdogra1299 pdogra1299 commented Jul 15, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Refines the quota-aware account ordering introduced in #1143/#1144. The previous comparator ranked accounts by soonest weekly (7d) reset, which ignores the window that actually expires first: the rolling 5h session. With two accounts whose sessions reset at different times, the session window closing soonest is the capacity that is about to be lost — it should be consumed first, regardless of the weekly schedule. The old ordering also considered session state only at hard exhaustion ("rejected"), so window handoffs happened reactively via 429s, and stale snapshots could misrepresent an account whose window had already reset.

Type of Change

  • Bug fix / behavior refinement (non-breaking)

Changes Made

  • Session-first ordering: usable accounts now rank by soonest 5h session reset. Session resets are compared in tolerance buckets (default 15 min, NEUROLINK_PROXY_SESSION_RESET_TOLERANCE_MS) so near-simultaneous resets count as equal and the soonest weekly reset breaks the tie; bucketing keeps the comparator transitive. Accounts with no ticking session window (fresh, not yet started) have nothing expiring and sort after ticking windows.
  • Session soft limit (default 0.97, NEUROLINK_PROXY_SESSION_SOFT_LIMIT): an account whose session utilization reaches the limit — or whose status is throttled — is demoted below accounts with headroom (never made unusable; still serves as fallback). The utilization snapshot is at least one response stale and requests arrive in concurrent bursts, so the small buffer makes the exhaustion handoff proactive and error-free instead of a burst of 429s at every window boundary. Saturated accounts order by soonest session reset (first back in service). Setting the limit to 1 disables demotion.
  • Reset freshening at read time: a window whose reset epoch has passed is treated as fresh (0 used, allowed, reset unknown) in every routing decision, so stale pre-reset numbers can never saturate or reject an account whose window Anthropic has since renewed. The snapshot then self-corrects from live response headers on the account's next request.
  • Probe-first for never-observed accounts and the configured-primary tie-break are unchanged.

Testing

  • New no-API suite test testSessionFirstOrdering (8 cases): session-first vs weekly, same-bucket weekly tie-break, 0.97 boundary (0.96 stays, 0.97/0.98 demote), throttled demotion, passed-reset freshening for both windows, both-saturated recovery order, env-configurable limit.
  • Runtime-verified 13 scenarios including all regressions from the prior ordering tests (weekly-first fallback when no session is ticking, probe-first, primary tie-break) — all pass.
  • pnpm exec vitest run test/proxyReliabilityHardening.test.ts — 36/36 pass (adjacent cooldown/quota persistence unaffected).
  • tsc --strict, ESLint gates, prettier, validate:all, and full build pass via the pre-commit hook.

Breaking Changes

  • No breaking changes. Existing env toggle NEUROLINK_PROXY_QUOTA_ROUTING still gates the whole feature; round-robin strategy is unaffected.

Summary by CodeRabbit

  • Bug Fixes
    • Improved quota-based account ordering by using session utilization limits and reset timing to prioritize more usable accounts.
    • Added more accurate handling for near/expired reset epochs so completed resets don’t incorrectly demote accounts.
    • Updated ordering rules to better account for soft-limit saturation, throttled status, and bucketed reset windows.
  • Tests
    • Added a continuous in-process test covering session-first ordering, throttling, soft-limit behavior, reset precedence, and tie-breaking.

@vercel

vercel Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
neurolink Ready Ready Preview, Comment Jul 15, 2026 4:11pm

@github-actions

github-actions Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: 9c0e71d4e8c3301076f7e335987cb8e3e83341a2
  • Message: fix(proxy): prioritize expiring session windows in account routing
  • Author: Parth Dogra

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e40a7656-f0af-4a50-8f39-0915f0d9271e

📥 Commits

Reviewing files that changed from the base of the PR and between eb52f62 and 9c0e71d.

📒 Files selected for processing (2)
  • src/lib/server/routes/claudeProxyRoutes.ts
  • test/continuous-test-suite-proxy.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/server/routes/claudeProxyRoutes.ts
  • test/continuous-test-suite-proxy.ts

📝 Walkthrough

Walkthrough

Claude proxy quota ordering now supports configurable session soft limits and reset tolerances, freshens passed resets, prioritizes session saturation and reset timing, and adds deterministic coverage for the updated ordering behavior.

Changes

Session-first quota routing

Layer / File(s) Summary
Session-aware quota metrics and comparator
src/lib/server/routes/claudeProxyRoutes.ts
Adds configurable session thresholds, saturation detection, reset bucketing, freshened reset handling, and session-first comparator tie-breaks.
Session-first ordering validation
test/continuous-test-suite-proxy.ts
Adds and registers deterministic tests for soft limits, throttling, reset freshening, tolerance buckets, and saturated-account ordering.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClaudeProxy as Claude proxy
  participant Metrics as accountSortMetrics
  participant Comparator as orderAccountsByQuota
  ClaudeProxy->>Metrics: evaluate account quota and reset state
  Metrics-->>Comparator: return usability, saturation, and reset buckets
  Comparator-->>ClaudeProxy: return ordered accounts
Loading

Possibly related PRs

Suggested reviewers: tara-ag

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main routing change: prioritizing expiring session windows in proxy account ordering.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/proxy-session-first-routing

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/server/routes/claudeProxyRoutes.ts`:
- Around line 700-704: Update the saturated-account comparison in
src/lib/server/routes/claudeProxyRoutes.ts:700-704 to remove the exact
sessionReset tie-break and rely on sessionResetBucket, preserving the configured
reset tolerance and weekly ordering. Add coverage in
test/continuous-test-suite-proxy.ts:1842-1848 with two saturated accounts in the
same reset bucket whose weekly resets verify the expected order.
- Around line 590-606: Update getSessionSoftLimit and getSessionResetToleranceMs
to parse the complete environment value with Number() so partially numeric
strings fall back to their defaults; additionally require the reset tolerance to
be an integer before accepting it.

In `@test/continuous-test-suite-proxy.ts`:
- Around line 1737-1745: Update testSessionFirstOrdering to save both
quota-related environment variables, set deterministic test values before
running its cases, and restore both original values in an outer finally block.
Ensure restoration preserves whether each variable was originally unset,
including the cleanup path covering the later case that deletes the soft limit.
- Around line 1842-1848: Add a test case near the existing “Both saturated”
scenario in the ordering tests that uses saturated accounts with session reset
times in the same tolerance bucket but opposing weekly reset times. Assert
ordering follows the earlier weekly reset as the tie-break, confirming tolerance
bucketing still enables weekly reset comparison.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 94a78bcc-83fe-4837-b3d5-3059b1d34031

📥 Commits

Reviewing files that changed from the base of the PR and between ebafce0 and eb52f62.

📒 Files selected for processing (2)
  • src/lib/server/routes/claudeProxyRoutes.ts
  • test/continuous-test-suite-proxy.ts

Comment thread src/lib/server/routes/claudeProxyRoutes.ts Outdated
Comment thread src/lib/server/routes/claudeProxyRoutes.ts Outdated
Comment thread test/continuous-test-suite-proxy.ts
Comment thread test/continuous-test-suite-proxy.ts Outdated

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Files reviewed: 2
New issues raised: 1 MINOR
Blocking issues: 0

Notes

  • The session-first ordering, soft-limit demotion, and reset-freshening logic in claudeProxyRoutes.ts is sound and well-documented.
  • Added one minor inline comment: the env parsers (getSessionSoftLimit / getSessionResetToleranceMs) are invoked inside accountSortMetrics, which is called repeatedly during sorting. Hoisting the parsed values once per orderAccountsByQuota call avoids both an O(N log N) env re-parse and the risk of a mid-sort env change breaking comparator transitivity.
  • Two of my observations overlap with feedback already posted by CodeRabbit (saturated-account exact sessionReset comparison and test env-variable isolation). I did not re-raise those as new blocking concerns.

No blocking criteria are met; approving.

Comment thread src/lib/server/routes/claudeProxyRoutes.ts
Comment thread src/lib/server/routes/claudeProxyRoutes.ts Outdated
Comment thread test/continuous-test-suite-proxy.ts
- Order accounts by soonest 5h session reset; weekly breaks ties.
- Demote sessions above a 97% soft limit before they hit 429s.
- Treat windows whose reset has passed as fresh at read time.
@pdogra1299

Copy link
Copy Markdown
Collaborator Author

Thanks @coderabbitai and @Tara-ag — all five findings verified and fixed, amended into the single commit (9c0e71d4):

  • Partial-numeric env values — both parsers now use Number() (tolerance additionally requires an integer), so "0.5oops" / "900000oops" fall back to defaults instead of being silently truncated.
  • Saturated tie-break honors tolerance + weekly (flagged by both reviewers) — removed the exact sessionReset comparison; saturated pairs now fall through to the same bucketed session ordering, with weekly deciding same-bucket ties. New test case covers two saturated same-bucket accounts with opposing weekly resets.
  • Env parsers hoisted out of the comparator — orderAccountsByQuota reads both thresholds once per sort and passes them into accountSortMetrics, so a mid-sort env change can never break transitivity (and it's cheaper).
  • Test env isolation — testSessionFirstOrdering saves both quota env vars, clears them for deterministic defaults, and restores them in an outer finally.

Re-verified: tsc/lint gates clean, 6/6 runtime checks for the fixes (garbage env → defaults, same-bucket saturated weekly tie-break, plus regressions), 36/36 proxyReliabilityHardening vitest tests, full pre-commit build.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cd . 2>/dev/null
rg -n "sessionResetBucket|SESSION_SOFT_LIMIT|SESSION_RESET_TOLERANCE|Number\(" src/lib/server/routes/claudeProxyRoutes.ts | head -60
echo "---"
rg -n "orderAccountsByQuota|accountSortMetrics" src/lib/server/routes/claudeProxyRoutes.ts | head -20

Length of output: 1331


Verification confirms the changes match what you described — Number() parsing with the integer check for tolerance (lines 591–605), env values hoisted and passed into accountSortMetrics at Line 695, and the saturated tie-break now falling through to bucketed session ordering (sessionResetBucket comparison at Line 716–717) rather than an exact sessionReset comparison. Everything lines up with your summary.

Thanks for the thorough writeup and re-verification, @pdogra1299!

ᕮ(⌐■_■)ᕭ

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Files reviewed: 2 (src/lib/server/routes/claudeProxyRoutes.ts, test/continuous-test-suite-proxy.ts)
New issues raised: 0
Decision: Approve

Assessment

This PR refines the proxy's quota-aware account ordering to prioritize the expiring 5h session window over the 7d weekly window, adds a soft-limit demotion for saturated sessions, and implements reset freshening at read time. The changes are localized to the proxy routing comparator and its test suite.

Key points verified:

  • Comparator transitivity: Session resets are compared via fixed-grid buckets (Math.floor(sessionReset / tolerance)), which is transitive by construction. The thresholds are read once per sort, so mid-sort env changes cannot break ordering.
  • Env parsing: Number() is used instead of parseFloat/parseInt, correctly rejecting partially numeric strings. The tolerance is required to be an integer.
  • Reset freshening: Windows whose reset epoch has passed are treated as fresh (sessionUsed = 0, status "allowed"), preventing stale snapshots from saturating an account after Anthropic has renewed its window.
  • Soft-limit behavior: Saturated/throttled accounts are demoted but remain usable as fallbacks, matching the documented intent.
  • Test coverage: The new testSessionFirstOrdering suite covers session-first vs weekly, same-bucket weekly tie-break, soft-limit boundary, throttled demotion, reset freshening, saturated recovery, and env-configurable limit. It also saves/restores both quota-related env variables.

Existing review comments

The outstanding review comments from earlier passes appear addressed in the current revision:

  • Env parsers are hoisted outside the comparator in orderAccountsByQuota.
  • Saturated accounts no longer use an exact sessionReset tie-break; they fall through to the same bucketed session → weekly → weekly-used chain.
  • The test wrapper saves and restores both NEUROLINK_PROXY_SESSION_SOFT_LIMIT and NEUROLINK_PROXY_SESSION_RESET_TOLERANCE_MS.

No new blocking or major issues were found. Approving.

@murdore
murdore merged commit e78a356 into release Jul 15, 2026
17 checks passed
@murdore
murdore deleted the fix/proxy-session-first-routing branch July 15, 2026 17:19
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 9.87.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

This branch was successfully deployed

1 active deployment
Preview — 9c0e71d4 Deployed Jul 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants