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.
88 lines
3.7 KiB
Markdown
88 lines
3.7 KiB
Markdown
# ADR-001: Reactive-core crate + per-engine crates
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
The store must present one reactive interface (notify, streams, queues,
|
|
locks, scheduler, outbox) over two backing engines, SQLite and Postgres.
|
|
The engines differ sharply in how much of that surface is natively
|
|
theirs:
|
|
|
|
- The **SQLite** engine rides honker's existing, battle-tested machinery
|
|
(published `honker-core` — a port-and-adapt of a sync library to the
|
|
family's async-facing-trait posture).
|
|
- The **Postgres** engine is the build-heavy side: LISTEN/NOTIFY wiring
|
|
and the pg-boss-family queue schema are built by this crate.
|
|
|
|
A single crate with feature-gated engines would force both engines'
|
|
dependency graphs into every downstream binary that enables both
|
|
features. That is not hypothetical: rusqlite 0.40's `libsqlite3-sys`
|
|
link collision with sqlx's sqlite driver is a real constraint
|
|
(see [ADR-003](003-sqlite-driver.md)); single-driver binaries are the
|
|
only clean escape.
|
|
|
|
Scope evidence lives in `docs/research/consumer-inventory.md`; the
|
|
operator decision was recorded 2026-10-04 against
|
|
OQ-ST-02 (`docs/research/phase-0.md`).
|
|
|
|
## Decision
|
|
|
|
The project ships as a **family of crates**:
|
|
|
|
1. **`alkstore` (core)** — the crate carrying the unified trait
|
|
surface, types, error model, capability flags, and the contract
|
|
documentation. No driver dependencies. Compile-lean by construction:
|
|
the base crate has no engine machinery to keep out.
|
|
2. **`alkstore-sqlite`** — the SQLite engine implementing the core
|
|
surface. Single driver: rusqlite + honker-core ([ADR-003]).
|
|
3. **`alkstore-postgres`** — the Postgres engine implementing the core
|
|
surface. Single driver: tokio-postgres + deadpool-postgres
|
|
([ADR-004]).
|
|
4. **A mem-shaped engine** (in-tree or separate test crate) may exist as
|
|
a third implementation for tests and doctests, if the test story
|
|
turns out to want it. Treated as an implementation convenience, not
|
|
a contract artifact — decided at implementation time, not now.
|
|
|
|
Downstream consumers depend on `alkstore` plus exactly one engine
|
|
crate. A consumer binary links at most one driver.
|
|
|
|
## Consequences
|
|
|
|
**Positive**
|
|
|
|
- The engines' asymmetry of work is structural: the SQLite engine has a
|
|
small, mostly-wiring job; the Postgres engine carries the build-heavy
|
|
LISTEN/queue work. Neither is burdened by the other's dependencies.
|
|
- Any future engine (alkfs's in-tree needs, an ops-surface engine) is
|
|
additive — a new crate implementing the core traits — rather than a
|
|
feature-graph edit to one crate.
|
|
- Core-lean is structural, not a feature-discipline to be enforced by
|
|
review.
|
|
- The libsqlite3-sys link-collision class of problems is eliminated by
|
|
construction (single-driver binaries).
|
|
- Per-engine compilation/test gates are independent.
|
|
|
|
**Negative**
|
|
|
|
- A version-coordination duty: the core's trait surface is a contract
|
|
the engine crates must track. Version bumps in core must be adopted
|
|
by engines in lockstep when the contract changes (minor/major
|
|
discipline; no trait-default drift).
|
|
- Slightly more crate plumbing; naming/publishing overhead.
|
|
- Consumers who want *both* engines in one binary (rare, unsupported-by
|
|
design) cannot get a both-features build today.
|
|
|
|
## References
|
|
|
|
- OQ-ST-02 (`docs/research/phase-0.md`) — the decision record with
|
|
options considered.
|
|
- `docs/research/consumer-inventory.md` — the inventory whose lean
|
|
(single crate) was superseded, with the correction recorded there.
|
|
- [ADR-003](003-sqlite-driver.md) — the SQLite driver choice whose
|
|
link-collision constraint motivates this split.
|
|
- [ADR-004](004-postgres-driver.md) — the Postgres driver choice.
|
|
- OQ-10 (`docs/architecture/open-questions.md`) — trait-versioning
|
|
duties created here. |