Skip to content

feat: preserve optional conversation account affinity across idle sessions - #365

Open
korkin25 wants to merge 1 commit into
icoretech:mainfrom
korkin25:feat/durable-conversation-affinity
Open

feat: preserve optional conversation account affinity across idle sessions#365
korkin25 wants to merge 1 commit into
icoretech:mainfrom
korkin25:feat/durable-conversation-affinity

Conversation

@korkin25

@korkin25 korkin25 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

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, then x-codex-conversation-id when the first header is absent. Codex's root-shared session-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 and prompt_cache_key are 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:

  • Full ordinary suite through 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.
  • Unix integration profile: 59 tests pass.
  • New focused coverage includes independent PostgreSQL transactions, initial reservation contention, stale completion after failover, lock waits past expiry, session recreation, scope/header validation, quota exclusion, actual HTTP 429/503 failover and no bounceback after account recovery. Existing LiveView coverage submits and reloads the new settings.
  • Disposable PostgreSQL 18 migration up/down/up preserves legacy rows/settings and parent records; restored defaults, index and retention bounds are verified.
  • Format, compile with warnings as errors, xref, strict Credo, docs check/build and independent source review pass.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants