-
Notifications
You must be signed in to change notification settings - Fork 1
Session Persistence
Edge adaptation of the upstream session event persistence backend.
Upstream reference: Session documentation
Upstream persists session events as append-only JSONL files — one file per session. The SessionPersistence interface defines the contract: materialize sessions, append event batches, list sessions, read history pages, commit crash-recovery repairs, and flush durability checkpoints. Events are lossless JSON with continuous sequence numbers.
DurableObjectSessionPersistence implements the upstream SessionPersistence interface using five Durable Object SQL tables:
| Table | Purpose |
|---|---|---|
| dsh_session_persistence_state | Schema version tracking |
| dsh_sessions | Session headers (id, cwd, version, parent, origin, incarnation) |
| dsh_session_events | Event log (session_id, seq, type, time, data as JSON text) |
| dsh_edge_blank_sessions | Pre-published blank sessions awaiting first prompt |
| dsh_session_summaries | Materialized session-list metadata |
Consecutive assistant/chunk, reasoning/chunk, and tool-call/chunk events are compressed into single storage rows (text-chunks, reasoning-chunks, tool-call-chunks) on write via packChunkRuns(). Decoded back to individual events on read via decodeStorageRecord(). Reduces DO SQL row count by 5–10× for long sessions.
dsh_session_summaries stores precomputed session-list metadata (updated_at, last_prompt_at, last_seq, blank, title). Updated atomically inside appendBatch()'s transaction. List operations read via SESSION_SUMMARY_MATERIALIZED — a single JOIN, no subqueries. The subquery-based SESSION_SUMMARY_SELECT exists only inside recomputeSummary() for boot-time stale-row repair.
- SessionPersistence interface contract
- Event format, sequence numbering, and append-only guarantee
- Flush/checkpoint semantics
- Crash-recovery repair via
commitRepair() - Session fork and seed mechanics
appendBatch() runs inside storage.transactionSync(): packs chunk runs, inserts storage records, increments revision, updates materialized summary — all atomic. A typical turn with 50 events (user message + request header + tool calls + assistant chunks + tool results + turn markers) produces ~10 storage rows after chunk packing.
SESSION_SUMMARY_MATERIALIZED is a SELECT ... FROM dsh_sessions JOIN dsh_session_summaries with pagination by updated_at DESC. No event-table access. O(page size).
History reads use SELECT ... FROM dsh_session_events WHERE session_id = ? AND seq BETWEEN ? AND ? with a configurable page limit (max 65,536 events). Packed rows are decoded on read. The client pages backward; goal/title state comes from the projection cache, not from scanning the full log.
syncSummaries() runs once per DO activation. Detects sessions where the summary revision doesn't match the session revision and recomputes them. Bounded by stale session count (typically zero after normal shutdown).
| Component | Category | Upstream Equivalent |
|---|---|---|
| DurableObjectSessionPersistence | Replace | JSONL file backend |
| Chunk packing | Replace | Not needed (file I/O has no row limit) |
| Materialized summaries | Replace | In-memory scan (not needed upstream) |
Key observation: Session persistence is the largest Edge-owned replacement — ~1,000 lines of DO SQL code. But it stays strictly within the upstream SessionPersistence interface. All optimizations (chunk packing, materialized summaries) are invisible to upstream plugins — they see the same append/read/flush contract.
- Home
- Architecture
- Core & Scope
- Session & Persistence
- Model & Context
-
Execution & Tools
- Tools
- Bash
- Subprocess 🚫
- PTY Session 🚫
- Background Jobs 🚫
- Filesystem
- LSP Navigation 🚫
- Code Runtime 🚫
-
Web Access
⚠️ -
Skills
⚠️ - Workflow 🚫
- Subagent 🚫
-
Policy & Interaction
- Goal
- Approval 🚫
- Permission Presets 🚫
-
Sandbox
⚠️ - Plan Mode 🚫
- User Interaction 🚫
- Commands 🚫
- Schedule 🚫
- Message Feedback 🚫
- Platform & Access
- Development
- 首页
- 架构
- 核心与作用域
- 会话与持久化
- 模型与上下文
- 执行与工具
- 策略与交互
- 平台与接入
- 开发