Skip to content

Add SessionStateStore seam with in-memory backend (tiering Nível 0)#102

Merged
renanfulas merged 2 commits into
mainfrom
codex/session-state-store-seam
Jun 29, 2026
Merged

Add SessionStateStore seam with in-memory backend (tiering Nível 0)#102
renanfulas merged 2 commits into
mainfrom
codex/session-state-store-seam

Conversation

@renanfulas

Copy link
Copy Markdown
Owner

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

  • Novo app/conversations/session_state.py: SessionState + SessionStateStore (Protocol) + InMemorySessionStateStore (TTL) + build_session_state_store_from_env() (flag SESSION_STATE_BACKEND).
  • Config: SESSION_STATE_BACKEND (memory|redis) + SESSION_STATE_TTL_SECONDS (default 2700 = 45min) + validação.
  • ChatFlowService: wrapper answer()_answer_inner() + _record_session_state que grava o estado fail-open, chaveado por hash_session (nunca session_id cru).
  • Wiring: store process-wide em app.state.chat_session_state_store; chat.py/web_chat.py injetam só quando PERSISTENCE_BACKEND=postgres.
  • Tech-plan Fase 1 marcada como implementada.

Garantias

  • Default no-op: sem store injetado, o hot path é idêntico ao de hoje (byte-for-byte).
  • Estado não-autoritativo (a verdade é o write-through no Postgres). Redis = Nível 1.
  • Backend redis ainda levanta NotImplementedError (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/20

Pendente (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

renanfulas and others added 2 commits June 29, 2026 15:21
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>
@renanfulas renanfulas merged commit 62f17a7 into main Jun 29, 2026
6 checks passed
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.

1 participant