117 lines
7.7 KiB
Markdown
117 lines
7.7 KiB
Markdown
---
|
|
status: stable
|
|
last_updated: "2026-10-11 (wave-8 gate: flipped stable — the family
|
|
picture frozen with the shipped thing; no further surface under
|
|
development)"
|
|
---
|
|
|
|
# alkstore — Overview
|
|
|
|
One reactive store interface over SQLite, Postgres, and the
|
|
in-process mem engine: durable
|
|
notify/subscribe signals, streams with per-consumer offsets, durable
|
|
queues with the transactional enqueue property, named locks, a
|
|
scheduler, and an outbox helper — with each engine using its own
|
|
native machinery underneath (SQLite: honker's watcher design;
|
|
Postgres: `pg_notify`/LISTEN and the pg-boss schema family; mem:
|
|
guarded in-process state, ephemeral by design —
|
|
[ADR-024](decisions/024-mem-engine.md)).
|
|
|
|
## Why this crate exists
|
|
|
|
The alk* ecosystem's current shape is a repository pattern with a
|
|
default in-memory adapter, cache-invalidation wiring in hot paths, and
|
|
per-project approximations where a durable reactive substrate was
|
|
needed. alkblobs paused partly on that fuzziness. alkstore is the
|
|
substrate, made once: the answer to "how does a change in the database
|
|
become visible to other processes/connections?" that downstream stores
|
|
don't re-derive.
|
|
|
|
## Crate family
|
|
|
|
Per [ADR-001](decisions/001-crate-split.md):
|
|
|
|
| Crate | Contents | Driver dependencies |
|
|
|---|---|---|
|
|
| `alkstore` (core) | trait surface, types, error model | none (no capability surface — [ADR-016](decisions/016-deployment-honesty.md): engine differences are compile-time identity + the deployment matrix, never a runtime descriptor) |
|
|
| `alkstore-sqlite` | SQLite engine ([ADR-003](decisions/003-sqlite-driver.md)) | rusqlite; the forked honker-core lineage rides in-tree as the engine crate's substrate module subtree ([ADR-011](decisions/011-sqlite-substrate-fork.md), designed in [ADR-012](decisions/012-forked-substrate-design.md), folded per [ADR-013](decisions/013-fold-substrate-into-sqlite.md)) |
|
|
| `alkstore-postgres` | Postgres engine ([ADR-004](decisions/004-postgres-driver.md)) | tokio-postgres, deadpool-postgres |
|
|
| `alkstore-mem` | mem engine — full contract v1, honest-ephemeral (no durability, single-process, never fleet-valid; [ADR-024](decisions/024-mem-engine.md)) | none (tokio sync + time only; the wasm32-clean member of the family) |
|
|
|
|
Downstream consumers depend on core + exactly one engine. Family
|
|
standards apply throughout: tokio async runtime, `thiserror` errors, no
|
|
panics in library code, no `unwrap()`/`expect()` outside tests,
|
|
lean base crate.
|
|
|
|
## Feature surface
|
|
|
|
Per [ADR-002](decisions/002-feature-scope.md):
|
|
|
|
- **First-class**: notify/listen; streams.
|
|
- **In scope**: named locks; queues + outbox helper; scheduler.
|
|
- **Cut-flag**: rate limits; result storage.
|
|
- **Out**: loadable-extension surface; DAGs/task
|
|
chains/chords/multi-writer replication/cross-machine locking.
|
|
|
|
## Document map
|
|
|
|
| Doc | Purpose |
|
|
|---|---|
|
|
| [core-contract.md](core-contract.md) | The unified trait surface: mechanisms, delivery guarantees, tx seam, naming |
|
|
| [engine-sqlite.md](engine-sqlite.md) | SQLite engine: mapping the contract onto the forked substrate module/rusqlite |
|
|
| [engine-postgres.md](engine-postgres.md) | Postgres engine: mapping the contract onto tokio-postgres/LISTEN |
|
|
| [engine-mem.md](engine-mem.md) | Mem engine: mapping the contract onto guarded in-process state (ADR-024) |
|
|
| [queues.md](queues.md) | Queue/scheduler/outbox semantics depth (ADR-009/ADR-010 resolved) |
|
|
| [deployment.md](deployment.md) | Host capabilities, connection budgets, deployment matrix (OQ-08 resolved) |
|
|
| [open-questions.md](open-questions.md) | OQ-01..NN tracker |
|
|
| [decisions/](decisions/) | ADRs |
|
|
|
|
## What is decided (ADR index)
|
|
|
|
| ADR | Decision | Status |
|
|
|---|---|---|
|
|
| [001](decisions/001-crate-split.md) | Reactive-core + per-engine crates | Accepted |
|
|
| [002](decisions/002-feature-scope.md) | Feature scope (inventory-confirmed) | Accepted |
|
|
| [003](decisions/003-sqlite-driver.md) | SQLite: rusqlite + honker-core lineage, bridged seam (ownership: ADR-011) | Accepted |
|
|
| [004](decisions/004-postgres-driver.md) | Postgres: tokio-postgres + deadpool, hand-rolled LISTEN | Accepted |
|
|
| [005](decisions/005-dependency-ownership.md) | Published libraries by default, named fork triggers | Accepted |
|
|
| [006](decisions/006-wake-and-delivery-contract.md) | Opaque wake + re-read; notify-vs-streams guarantee split | Accepted |
|
|
| [007](decisions/007-transactional-seam.md) | Caller-held `TxHandle` with `*_tx` methods | Accepted |
|
|
| [008](decisions/008-contract-v1-pinning.md) | Contract v1 surface pinning (partition, TxHandle shape, wake type, reserved strings, error taxonomy) | Accepted |
|
|
| [009](decisions/009-scheduler-collapse.md) | Scheduler collapse (queues + `schedule()`, `@every`-only) | Accepted |
|
|
| [010](decisions/010-queue-semantics-depth.md) | Queue semantics depth (visibility, backoff, dead-letter, sweep, layout) | Accepted |
|
|
| [011](decisions/011-sqlite-substrate-fork.md) | SQLite substrate — fork honker-core into owned code | Accepted |
|
|
| [012](decisions/012-forked-substrate-design.md) | Forked substrate design (contract-blind boundary, fidelity, port deltas) | Accepted |
|
|
| [013](decisions/013-fold-substrate-into-sqlite.md) | Fold the forked substrate into `alkstore-sqlite` (no fourth crate) | Accepted |
|
|
| [014](decisions/014-outbox-tx-enqueue.md) | Transactional outbox enqueue (`outbox_enqueue_tx` on `TxHandle`) | Accepted |
|
|
| [015](decisions/015-streams-depth.md) | Streams depth (carried-metadata keys, global-FIFO ordering, `StreamEvent`, `trim_to`) | Accepted |
|
|
| [016](decisions/016-deployment-honesty.md) | Deployment honesty (no runtime capability surface; compile-time identity + matrix) | Accepted |
|
|
| [017](decisions/017-contract-versioning.md) | Contract versioning (core crate's semver is the contract version; change classes, pairing carriers, lockstep duties) | Accepted |
|
|
| [018](decisions/018-provenance-register-and-cherry-picks.md) | Substrate provenance register and cherry-pick procedure (`PROVENANCE.md` in-tree, per-delta entries) | Accepted |
|
|
| [019](decisions/019-mechanism-handle-surfaces.md) | Mechanism-handle surfaces (handle traits, `Job`/`Schedule` shapes, `worker_id`, `StopToken`) | Accepted |
|
|
| [020](decisions/020-enqueue-opt-semantics-and-bridges.md) | Enqueue-option semantics (delay/run_at, expires, scheduler stamp source, payload encoding) | Accepted |
|
|
| [021](decisions/021-tx-reads-and-value-shape-fixes.md) | Third review round (tx-read methods on `TxHandle`, `Job.claimed_at`, `schedule()` queue-argument validation, drop = rollback, receiver close/error arms) | Accepted |
|
|
| [022](decisions/022-contract-suite-layout.md) | Contract-suite layout (shared internal suite crate, store-factory parameterization) | Accepted |
|
|
| [024](decisions/024-mem-engine.md) | The mem engine (`alkstore-mem` — full contract v1, honest-ephemeral, wasm32 compile-clean acceptance) | Accepted |
|
|
|
|
## Non-goals
|
|
|
|
- Not a database abstraction/ORM: the store covers the reactive
|
|
coordination surface, not general row storage (consumers keep their
|
|
own engines/schema for business data, sharing the connection when
|
|
appropriate — the outbox pattern).
|
|
- Not a network service: no transport; any networked ops surface rides
|
|
alkcall and is a separate future decision (store layer stays
|
|
substrate-free, the alkblobs store-layer precedent).
|
|
- Not multi-machine on SQLite: single-host honesty is inherited
|
|
([deployment.md](deployment.md); the boundary's location in the
|
|
surface is decided — [ADR-016](decisions/016-deployment-honesty.md)).
|
|
|
|
## Evidence base
|
|
|
|
Phase 0 (`docs/research/phase-0.md`) is complete: two POCs
|
|
(`poc-sqlite-posture-findings.md`, `poc-pg-posture-findings.md`) passed
|
|
all gate conditions; the consumer inventory
|
|
(`consumer-inventory.md`) graded every feature row. The Phase 1
|
|
architecture work runs over that complete evidence base; open Phase 1
|
|
work is tracked in [open-questions.md](open-questions.md). |