Skip to content

Route all SQLite writers through append-only spools (single-writer architecture) #47

Description

@khaliqgant

Problem

Multiple independent OS processes write ai-history.db directly: ai-hist sync, the MCP server, and agent-relay brokers. SQLite WAL permits exactly one writer, and the write lock belongs to a process, not a lease. Any writer that dies, hangs, or is suspended mid-transaction wedges every other writer permanently.

This is not hypothetical. A multi-day sync outage was traced to two agent-relay processes in state T (SIGSTOP'd), one frozen mid-write-transaction. A stopped process never runs again on its own, so the lock was held indefinitely. sqlite3 with a 10s busy timeout waited the full 10s and still failed.

No timeout, retry, or backoff survives this. #44, #45, and #46 reduce the blast radius and make it diagnosable; none make it impossible.

Proposal

Only ai-hist sync opens the database read-write. Every other producer appends to its own append-only JSONL spool; sync ingests them with a byte-offset cursor.

This is already the proven model in this codebase — ~/.claude/history.jsonl and ~/.codex/history.jsonl are exactly this, and sync_jsonl_incremental is the consumer. Extending it to agent-relay and the MCP server means reusing a working pattern rather than inventing one.

Why it's decisive:

Notes

Deserves an ADR — it changes the write path for every producer. crates/ai-hist-core/src/outbox.rs already establishes cursor/watermark conventions to build on.

Related: #44, #45, #46

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions