feat: preserve optional conversation account affinity across idle sessions - #365
Open
korkin25 wants to merge 1 commit into
Open
feat: preserve optional conversation account affinity across idle sessions#365korkin25 wants to merge 1 commit into
korkin25 wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a conversation pauses long enough for its transport session to expire, its next request can select a different account even though the previous account remains eligible. This adds optional per-pool conversation affinity in PostgreSQL so the same conversation can keep its account across idle session recreation and requests handled by different application processes.
The setting is off by default. Enabling it uses
thread-id, thenx-codex-conversation-idwhen the first header is absent. Codex's root-sharedsession-id, window IDs, turn state and prompt-cache keys are not treated as conversation identity. Stored keys are typed digests scoped to the pool, API key and exposed model; outgoing payloads andprompt_cache_keyare unchanged.The preference only reorders eligible candidates. Existing previous-response/file constraints, active upstream WebSocket pins, quota/health exclusions and retry rules retain priority. The first reservation converges under concurrent requests, and successful failover updates the remembered account. A row-ID/generation fence prevents an old completion from moving it back or overwriting a recreated row. Owner leases remain a separate mechanism; this PR does not depend on #364's code.
Retention defaults to one day, accepts 60 seconds to 30 days, and renews only on successful completion. Expired mappings are ignored immediately and removed in indexed batches of at most 1,000. Disabling applies to new route plans; already admitted plans may finish fenced bookkeeping. The migration extends the existing affinity table and pool settings. Rollback removes only the new affinity kind and fields, preserving legacy rows.
Validation:
make test-fast N=4: all four partitions pass. An initial run exposed the existing cleanup-summary assertion's missing new zero-valued counter; that contract assertion is updated.Cross-process coordination is tested using separate committed PostgreSQL connections, not a production multi-node cluster. Account affinity may improve cache locality; it does not guarantee provider cache hits or transfer provider state between accounts. No production rollout is included.