--- id: store-sqlite-construction name: sqlite constructor wiring — the default-build store shapes status: completed depends_on: [engine-sqlite, engine-sqlite-window] scope: narrow risk: low impact: component level: implementation tags: [wave-3, store, sqlite, construction] --- ## Description Slot sqlite into the facade's engine representation — the slotting-in pattern `src/store.rs`'s module doc pinned ("adding an enum variant and a named constructor is slotting in"): - **`KvEngine::Sqlite`** variant behind `#[cfg(feature = "sqlite")]` + the dispatch arms (`put`/`get`/`has`/`size`/`delete`/`list`). The kv cursor dispatch (`AnyCursor`'s kv arm) carries the sqlite materializing body — the kv-arm shape over multiple kv engines (a `KvCursor` sub-enum vs per-engine variants) is a recorded design point. The `#[allow(unused_variables)]` empty-set scaffolding on the `KvEngine` methods shrinks (the kv set is no longer empty in default builds); `backend.rs`'s `#![allow(dead_code)]` scope note about "the kv engines' whole-value `put` before wave 3" is updated to the landed state. - **Named constructors**, feature-gated on `sqlite` (default-on — the default build constructs them): - **dual-tier** `kv = sqlite + large = local` — the default-build production shape; fallible (file I/O: opening/creating the database, creating the local root). Size-threshold dispatch at the constructor-tunable threshold as in the mem+local shape. - **kv-only(sqlite)** — no large tier; `threshold` is the put-time rejection point (ADR-012 §6.2; the rejection machinery is the put seam's, already landed — only the constructor slots in). - Both take the **delete-window delay** parameter (ADR-008 §2: the delete window's delay, **default 5 min, constructor-tunable per deployment** — a named shipped-default constant; `Duration`). This is the durable window's cadence knob the sweep's SQL-backed form consumes (`store-sweep-durable-window`); `0` is a legal degenerate tuning (execute-on-next-sweep — the test tuning). The mem/local constructors are unchanged: the inline form has no delay in effect. - **`ensure_gc_schema` at construction** — the store-core call (engine-neutral; sqlite's body creates `gc_window` only). A construction failure is `Err(Error::Io)` per the fallible-constructor pattern `dual_tier_mem_local` set. - **The one-window-host rule's store-core posture** (ADR-012 §5): the durable window hosts on **the kv engine when it is SQL-backed** — sqlite hosts. Recorded (code shape or doc note) so wave 5's pg-lo dormancy (the dual-SQL instance stages on the kv engine only) slots in without reshaping. - **Constructor unit tests**: the modes construct and introspect correctly (`mode()`/`threshold()`), `ensure_gc_schema` ran (the window table exists in the fresh database), the window-delay default is the pinned constant, kv-only rejection wiring unchanged, the dual-tier shape round-trips end-to-end (a smoke put/get through both tiers). ## Acceptance Criteria - [x] `KvEngine::Sqlite` slots in; all six kv ops dispatch; the kv cursor body dispatches (design point recorded) - [x] `dual_tier_sqlite_local` + `kv_only_sqlite` constructors exist behind feature `sqlite`, take threshold + window delay, fallible where I/O is fallible - [x] `ensure_gc_schema` runs at construction; the window-delay shipped default is 5 min (pinned constant) and constructor-tunable; `0` legal - [x] The one-window-host posture recorded (sqlite hosts when the kv engine is SQL-backed) - [x] The stale empty-set scaffolding/allow notes updated to the landed state - [x] `cargo test` (default) green — the default build constructs and exercises sqlite stores; `cargo clippy --all-targets -- -D warnings` and `cargo fmt --check` green ## References - src/store.rs (the engine-representation design point; the constructor modes; the slotting-in pattern) - docs/architecture/decisions/011-vocabulary-tiers-engines-and-fleet-state.md §4 (modes) - docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §6.3 (dual-tier shapes), §5 (the one-window-host rule) - docs/architecture/decisions/008-trait-size-probe-fleet-gc-and-large-engines.md §2 (the window delay, default 5 min) - docs/architecture/decisions/013-family-composition-reactive-boundary-and-feature-graph.md §4 (the feature graph) ## Notes - **KvCursor sub-enum (the recorded design point).** The kv cursor dispatch went with a `KvCursor` sub-enum behind `AnyCursor`'s one `Kv` arm (rather than a per-engine `AnyCursor::Kv*` variant pair): per-engine variants would copy the kv materializing arm and its consumers (the verification-on-get body, `Blob`'s drive) per engine without adding a behavior; the sub-enum keeps `AnyCursor` a two-arm tier dispatch. Postgres (wave 4) slots one arm into `KvCursor`. - **`KvEngine::ensure_gc_schema` — the engine-neutral store-core call** lives on the kv-tier enum itself: the sqlite arm forwards to the `EngineWindowState` clause; the mem arm is structurally nothing (the in-process engines execute the ADR-005 window protocol inline and carry no GC schema). Both sqlite constructors dispatch through it — the store core calls the kv engine, never a typed sqlite path, which is the recording shape the one-window-host posture wanted. - **The window delay** is a named shipped constant (`DEFAULT_DELETE_WINDOW_DELAY`, 5 min, ADR-008 §2) re-exported from `lib.rs`; both sqlite constructors take it explicitly (`Duration`, `Duration::ZERO` the legal degenerate tuning) and the store carries it as a `window_delay` field with a crate-internal accessor (`Store::window_delay`) for the durable sweep form (`store-sweep-durable-window`) to consume. The mem/local constructors are signature-unchanged; they carry the constant, never consulted (the inline form has no delay in effect — same posture as the mem-only threshold field). - **Fallibility split**: `dual_tier_sqlite_local(database, root, threshold, window_delay)` is fallible on the database file I/O, `ensure_gc_schema`, *and* the local root creation (all `Err(Error::Io)` via `?`); `kv_only_sqlite(database, threshold, window_delay)` on the first two. WAL engagement failure (e.g. `:memory:`) is a construction error, per the engine's recorded posture. - `SqliteBackend` gained a `#[cfg(test)] table_exists` probe (the sqlite_master instrument) so the store tests can observe the schema from the facade side; sqlite.rs's own test helper now delegates to it. - The stale empty-set scaffolding is updated to the landed state: the `#[allow(unused_variables)]` attrs came off the `KvEngine` methods; the scope notes in store.rs, backend.rs (whole-value `put` now has its in-tree callers), sqlite.rs (nothing-constructs-the-engine), and gc.rs (the window family's first caller) reflect the landed state. `--no-default-features` builds (kv set genuinely empty again) still compile under their own cfg arithmetic — verified along with the default, mem-only, and all-features builds. ## Summary Sqlite slotted into the facade's engine representation (wave 3 construction; commit pending at write time): `KvEngine::Sqlite` with all six kv-op dispatch arms, the `KvCursor` sub-enum carrying the sqlite materializing body behind `AnyCursor`'s kv arm (design point recorded), the two named constructors (`dual_tier_sqlite_local` — the default-build production shape, and `kv_only_sqlite`) taking threshold + the constructor-tunable delete-window delay (`DEFAULT_DELETE_WINDOW_DELAY` pinned at 5 min, `0` legal), `ensure_gc_schema` running at construction through the engine-neutral `KvEngine` call, the one-window-host posture recorded in the module doc (the durable window is the kv engine's when the kv engine is SQL-backed — wave 5's pg-lo dormancy slots in without reshaping), and all stale empty-set allow/scope notes updated to the landed state. Verification: `cargo test` 62 passing (default build — the 5 new sqlite-construction tests construct, introspect, schema-probe, rejection-check, and end-to-end round-trip both tiers), `cargo test --all-features` 117, `cargo test --features mem` 117, `--no-default-features --features mem` 97, clippy `-D warnings` (default + all-features) clean, `cargo fmt --check` clean, and `cargo doc --no-deps` at the pre-existing warning baseline.