feat(routing): session-affinity max-requests with per-model/provider rules - #4654
feat(routing): session-affinity max-requests with per-model/provider rules#4654dangxia wants to merge 3 commits into
Conversation
Cap sticky session→auth picks via global max-requests and optional provider/model overrides, rebinding when the limit is reached.
|
This pull request targeted The base branch has been automatically changed to |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6065dc79fb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a3268d8a4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return nil, err | ||
| } | ||
|
|
||
| maxRequests := resolveSessionAffinityMaxRequests(s.maxRequests, s.rules, provider, model) |
There was a problem hiding this comment.
Resolve affinity rules against the selected provider
When session affinity is used on a multi-provider route, pickNextMixedLegacy invokes this selector with provider == "mixed", so resolveSessionAffinityMaxRequests can only match model-only/global rules and never matches a rule configured for the actual execution provider such as provider: "xai". In that setup, a provider-specific session-affinity-rules max-requests override is silently ignored for mixed routing, leaving those sessions sticky for the global limit instead of the configured provider limit.
Useful? React with 👍 / 👎.
When the routing key is "mixed", resolve session-affinity max-requests against the bound auth's execution provider so provider-specific rules are not skipped. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Summary
Add session-affinity max-requests so sticky session→auth bindings can rebind after a request cap, with optional per-provider / per-model overrides.
Motivation
Session affinity keeps a client on the same credential for continuity, but long-lived sessions can pin traffic to one account indefinitely (until TTL expires or the auth becomes unavailable). Operators need a way to:
without turning off session affinity entirely.
Changes
Config
routing.session-affinity-max-requests— global default (<=0/ omit /-1= unlimited)routing.session-affinity-rules[]— optional overrides:provider(optional)model(optional; thinking-suffix stripped for matching)max-requestsMatch specificity (most specific wins):
provider+model>model-only>provider-only> global defaultEqual-specificity rules keep declaration order (first match wins at equal score).
Runtime
hits > max-requests, invalidate the binding and re-pick via the fallback selector, then rebindDocs / example
config.example.yamldocuments the new knobs and the fill-first + max-requests interactionBehavior notes / caveats
Only effective when
routing.session-affinity: true.Example
Test plan
max-requests reached) and hit counters on cache hitsFiles
internal/config/config_types.go— config typesconfig.example.yaml— example + caveatssdk/cliproxy/auth/session_cache.go— hit counting + alias-group invalidatesdk/cliproxy/auth/session_affinity_rules.go— compile / resolvesdk/cliproxy/auth/selector.go— max-requests rebind pathsdk/cliproxy/service_config.go— wire config → selector + hot-reload equality