docs/architecture/ now exists: README index, overview, five component specs (core-contract, engine-sqlite, engine-postgres, queues, deployment), ADR-001..007 carrying the Phase 0 resolved decisions (crate split, feature scope, per-engine drivers, dependency ownership, wake contract, tx seam), and the centralized open-questions tracker promotion: OQ-ST-01..08 mirror to OQ-01..08 one-to-one with statuses/resolutions carried; new Phase 1 questions append (OQ-09 scheduler collapse, OQ-10 contract versioning). Open Phase 1 work: OQ-04 contract pinning (high), OQ-05 queue semantics depth (high), OQ-06 honker-core quality read (high; fork-trigger gate), OQ-08 capability surface, OQ-09, OQ-10. Erratum fixed in phase-0 OQ-ST-04 (thread-affinity friction is SQLite-side, previously garbled as pg-side) and a stale scheduler- boundary pointer corrected in consumer-inventory.md. Two review passes run (findings: OQ-promotion numbering faithfulness, ADR back-reference sync) — all critical/warning findings resolved.
114 lines
5.5 KiB
Markdown
114 lines
5.5 KiB
Markdown
---
|
||
status: draft
|
||
last_updated: 2026-10-04
|
||
---
|
||
|
||
# SQLite engine
|
||
|
||
The `alkstore-sqlite` engine implements
|
||
[core-contract.md](core-contract.md) on rusqlite + published
|
||
honker-core. This spec records WHAT the engine is internally (its
|
||
connection architecture, seam, and wake plumbing) — not code-level
|
||
HOW. Decisions live in ADRs; per-contract obligations live in the core
|
||
spec and are not restated here.
|
||
|
||
## Identity and posture
|
||
|
||
- Single driver: rusqlite (riding
|
||
[honker-core's pin](decisions/003-sqlite-driver.md)),
|
||
`bundled-sqlite` for hermetic builds. No `.so` runtime artifacts, no
|
||
vendored patches
|
||
([ADR-003](decisions/003-sqlite-driver.md),
|
||
[ADR-001](decisions/001-crate-split.md)).
|
||
- Sync machinery, async-facing trait: honker-core is sync (std
|
||
threads, blocking iterators); the engine bridges at the trait seam
|
||
per the family-standard posture (alktty REQ-TTY-01 precedent).
|
||
Every engine call runs in `spawn_blocking`.
|
||
- Single-host by nature: file-backed, one machine, NFS-two-writers
|
||
unsupported (honker's honesty posture, inherited). See
|
||
[deployment.md](deployment.md).
|
||
|
||
## Connection architecture
|
||
|
||
- **Writer** — one dedicated connection; the only one permitted to
|
||
write. Serializes all mutations (WAL single-writer, modeled
|
||
honestly, not fought).
|
||
- **Readers** — a small pool of read connections for lookups and
|
||
claim/ack work.
|
||
- **Watcher** — honker-core's `SharedUpdateWatcher`: a dedicated
|
||
thread polling `PRAGMA data_version` at the default 1 ms cadence,
|
||
fanning out to listeners, overtriggering on purpose (waking all
|
||
subscribers per poll tick, even when several commits coalesced
|
||
inside one tick — wake is a hint; consumers re-read indexed state,
|
||
[ADR-006](decisions/006-wake-and-delivery-contract.md)).
|
||
- Each connection runs honker's bootstrap at open: pragmas
|
||
(WAL, `synchronous=NORMAL`, busy timeout), `attach_notify`,
|
||
`attach_honker_functions`, `bootstrap_honker_schema` (the
|
||
alknet-filesystem POC's wiring shape).
|
||
|
||
## Mapping the contract
|
||
|
||
| Contract piece | Engine realization |
|
||
|---|---|
|
||
| notify / listen | honker's notify functions inside the caller's tx; `listen()` bridges the watcher's fanout into a tokio receiver (one `spawn_blocking` thread per subscription doing `blocking_send`) |
|
||
| streams | honker's stream machinery; explicit offset saves through the tx seam |
|
||
| queues | honker's queue functions ([ADR-002](decisions/002-feature-scope.md)); semantics depth design in [queues.md](queues.md) |
|
||
| named locks | honker's lock machinery |
|
||
| scheduler / outbox | honker's counterparts, per [queues.md](queues.md) |
|
||
| begin_tx | acquires the writer slot, opens `BEGIN IMMEDIATE`, returns the caller-held handle ([ADR-007](decisions/007-transactional-seam.md)) |
|
||
| handle ops | each `*_tx` op round-trips `spawn_blocking` to the same connection (thread-affinity note in [ADR-007](decisions/007-transactional-seam.md)) |
|
||
| commit/rollback | releases the writer slot |
|
||
|
||
## Obligations and constraints
|
||
|
||
- **A long transaction parks the writer** (the slot lease is the
|
||
honest model). Contract docs must surface this so consumers budget
|
||
transactions ([ADR-007](decisions/007-transactional-seam.md) negative
|
||
consequence).
|
||
- Watcher failure handling is inherited: on watcher death, every
|
||
subscriber's receiver closes (`WatcherDeathGuard` behavior) —
|
||
consumers see the close, never a silent hang
|
||
([ADR-006](decisions/006-wake-and-delivery-contract.md)).
|
||
- Wake coalescing: bursts inside one poll tick produce one wake;
|
||
correctness is preserved by the re-read contract
|
||
(POC-pinned: missed-wake stress with correct post-burst re-reads).
|
||
- **Deployment note**: honker-core 0.5 pins rusqlite ^0.40.1, whose
|
||
rustc floor is ≥ 1.99; binaries linking this engine carry that
|
||
requirement ([deployment.md](deployment.md) matrix).
|
||
- The optimization path, if seam throughput ever demands it: a
|
||
dedicated std-thread bridge (one thread owning the writer conn, ops
|
||
over mpsc — measured ~2× the spawn_blocking shape at p50 in POC #1),
|
||
or a raised watcher cadence for idle CPU. Neither is the default.
|
||
|
||
## What rides on the fork question
|
||
|
||
Nearly all of honker-core's surface is consumed (Writer/Readers/
|
||
SharedUpdateWatcher/attach_*). The [quality read
|
||
(OQ-06)](decisions/005-dependency-ownership.md) is this engine's only
|
||
open dependency gate: if it names a defect or an upstream-unwon't
|
||
change, the fork posture
|
||
([ADR-005](decisions/005-dependency-ownership.md)) fires and this
|
||
engine's substrate becomes owned code. Until then, published-library
|
||
consumption stands.
|
||
|
||
## Design Decisions
|
||
|
||
| ADR | Decision | Summary |
|
||
|---|---|---|
|
||
| [001](decisions/001-crate-split.md) | Crate split | single-driver engine crate |
|
||
| [002](decisions/002-feature-scope.md) | Feature scope | which rows this engine serves |
|
||
| [003](decisions/003-sqlite-driver.md) | Driver | rusqlite + honker-core, bridged seam, inherited watcher |
|
||
| [005](decisions/005-dependency-ownership.md) | Ownership | published honker-core; named fork triggers |
|
||
| [006](decisions/006-wake-and-delivery-contract.md) | Wake contract | data_version watcher, coalescing, death-closes-receivers |
|
||
| [007](decisions/007-transactional-seam.md) | Tx seam | writer-slot lease, `BEGIN IMMEDIATE`, `spawn_blocking` round-trips |
|
||
|
||
## Open Questions
|
||
|
||
Open questions are tracked in
|
||
[open-questions.md](open-questions.md). Key
|
||
questions affecting this document:
|
||
|
||
- **OQ-06**: honker-core quality read — fork-trigger assessment (open)
|
||
- **OQ-09**: scheduler collapse into queues (shared with
|
||
[queues.md](queues.md)) (open)
|
||
- **OQ-05**: queue semantics depth on honker's machinery (open) |