Add SessionStateStore seam with in-memory backend (tiering Nível 0)#102
Merged
Conversation
Adds the concrete operational design agreed in the 2026-06-29 architecture discussion: the per-turn flow (one synchronous Postgres transaction that persists the turn and enqueues the outbox; fail-open hot state; async off-box backup via the worker) and the handoff flow (the support_case + handoff.requested in the same sync transaction is the consistency gate; async external delivery). Clarifies that Redis only ever enters as a non-authoritative hot-state backend / read cache (levels 1-2), never as the durability anchor. Makes the plan self-contained. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First code slice of the layered-persistence plan: a stable, swappable hot-tier session-state seam mirroring ConversationArchiveSink. Adds app/conversations/session_state.py (SessionState, SessionStateStore Protocol, InMemorySessionStateStore with TTL, build_session_state_store_from_env), the SESSION_STATE_BACKEND / SESSION_STATE_TTL_SECONDS config, and wires ChatFlowService to write the state fail-open via an answer() wrapper (keyed by hash_session, never a raw session_id). The store is process-wide in app.state and injected by the /chat and /web routes only under PERSISTENCE_BACKEND=postgres. Default no-op: with no store injected the hot path is byte-for-byte unchanged. The state is non-authoritative (truth stays in the Postgres write-through). The reader, the Redis backend (Nível 1), and migrating the transport escape state come next. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
O que foi feito
Primeira fatia de código do plano de persistência em camadas (decisão A): o seam de estado quente de sessão, trocável e com default seguro, espelhando o
ConversationArchiveSink.Mudanças
app/conversations/session_state.py:SessionState+SessionStateStore(Protocol) +InMemorySessionStateStore(TTL) +build_session_state_store_from_env()(flagSESSION_STATE_BACKEND).SESSION_STATE_BACKEND(memory|redis) +SESSION_STATE_TTL_SECONDS(default 2700 = 45min) + validação.ChatFlowService: wrapperanswer()→_answer_inner()+_record_session_stateque grava o estado fail-open, chaveado porhash_session(nuncasession_idcru).app.state.chat_session_state_store;chat.py/web_chat.pyinjetam só quandoPERSISTENCE_BACKEND=postgres.Garantias
redisainda levantaNotImplementedError(próxima fatia).Validação
python -m pytest→ 609 passed, 31 skipped (+14 novos)python -m compileall app tests✓run_domain_eval vendas→ 12/12 ·suporte-vps-whatsapp→ 20/20Pendente (próximas fatias)
Leitor do estado (consumo), backend Redis (Nível 1), e migrar o estado de escape do transporte Hermes para o mesmo seam.
🤖 Generated with Claude Code