Files
alkstore/tasks/sqlite-engine-integration.md
T

200 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: sqlite-engine-integration
name: SQLite engine — integration (lint removal, full-surface wiring, suite adoption)
status: completed
depends_on: [sqlite-engine-notify-listen, sqlite-engine-streams, sqlite-engine-queues, sqlite-engine-locks, sqlite-engine-scheduler-outbox]
scope: moderate
risk: medium
impact: phase
level: implementation
tags: [wave-3, sqlite-engine, integration]
---
## Description
Close the wave's integration gaps once every mechanism is wired:
- **Remove the two lint suppressions** in
`alkstore-sqlite/src/substrate/mod.rs` (`#![allow(dead_code)]`,
`#![allow(unused_imports)]`) — the waves-1–2 review's explicit
wave-3 obligation. With the engine layer wired, every substrate
surface should be reachable; genuinely dead ported code must be
**cut, not suppressed** (and the cut registered in PROVENANCE.md if
it diverges from the lineage's kept set — ADR-018's delta
discipline). Fix whatever the lints surface; do not re-add allows.
- **Full-surface sweep**: every `Store`/`TxHandle`/mechanism trait
method implemented (no `todo!`/`unimplemented!` anywhere); the
engine crate's lib re-exports its public surface (`open`,
`SqliteOpts`, the concrete store type) per the module-per-file
convention.
- **Contract-suite adoption** (the plan's "waves 3 and 4 adopt the
harness"): implement `StoreFactory` for the SQLite engine (fresh
temp-file store per `open`, idempotent teardown) and wire the
engine's backlog column — the rows this engine owns now, per
ADR-023's verification-backlog additions and the engine-scoped
backlog rows:
- Extent-clamp semantics (`claim_batch(n <= 0)`, stream reads
`limit <= 0`) — stamped `ADR-023 §2`
- Duration-refusal (`try_lock`/`renew` with `ttl <= 0`) — stamped
`ADR-023 §2`
- `encode_payload` typed-failure round-trip (enqueue/publish store
+ decode the exact serialization) — stamped `ADR-023 §1`
- Plain-path open (`?name=value` suffix = literal filename) —
stamped `ADR-023 §3`
- Poll-cadence default + knob (config-surface accounting, not
wall-clock) — stamped `ADR-023 §4`
- The engine-scoped rows core-contract.md assigns this engine:
`PayloadTooLarge` never produced (ADR-016 §5), drop = rollback
no-ghosts (ADR-021 §4), in-tx read-your-own-writes (ADR-021 §1),
enqueue-opts resolution (ADR-020 §1–§3), receiver close arms
(ADR-021 §5) — each stamped per the suite's convention.
Rows run against the SQLite factory now; wave 5 runs the same rows
against pg (the factory-parameterized point).
- **Crate docs**: the engine crate's lib-level doc comments state the
single-host posture and the writer-parking honesty note (ADR-016,
ADR-007's negative consequence) — the identity statements this
crate owns.
- **Gates**: full workspace build/test/clippy/fmt; coverage spot-check
on the engine crate (no large uncovered regions outside error arms).
## Acceptance Criteria
- [x] Both `#![allow]` lints removed from `substrate/mod.rs`; any
code the removal surfaces is cut (and registered) or wired —
clippy `-D warnings` green without them
- [x] No `todo!`/`unimplemented!` in the engine crate; full trait
surface implemented
- [x] `StoreFactory` implemented for SQLite; the backlog-column rows
listed above exist, version-stamped, and run green against the
SQLite factory
- [x] Engine crate lib docs carry the single-host + writer-parking
posture statements
- [x] Workspace gates green: `cargo build`, `cargo test`, clippy
`-D warnings`, fmt clean
## References
- docs/reviews/001-waves-1-2-general-review.md (§2 smells, §7)
- docs/architecture/decisions/023-fourth-review-round.md (Verification backlog additions)
- docs/architecture/core-contract.md (§Verification backlog)
- docs/architecture/decisions/022-contract-suite-layout.md
- docs/architecture/decisions/016-deployment-honesty.md
- alkstore-contract-suite/src/factory.rs
## Notes
> Decisions of record the description didn't pin:
- **Lint removal cut six substrate items, registered D-32..D-36** —
lifting the two `#![allow]`s surfaced six genuinely dead surfaces,
all cut rather than wired, each an ADR-018 register entry with its
reason: `arg_opt_i64` (upstream consumed it at the optional-arg SQL
entry points whose queue functions D-04 dropped — the re-derivation
resolves opts engine-side), `ops::now_unix` (the fold D-17 gave
each module region its own clock read; `resolution.rs` owns the
engine layer's single clock), `queue_next_claim_at` (upstream's
external-poll-driver function; the v1 scheduler surface has no
next-wake query — the engine's leader loop derives the boundary
from `scheduler_tick` + `scheduler_soonest`), `Writer::try_acquire`
(a try-shaped begin doesn't exist on the contract — `begin_tx`
*parks* on the lease by design, ADR-007; a try-acquire would
contradict the posture), and `UpdateWatcher::spawn` /
`SharedUpdateWatcher::new` (the config-less convenience twins —
this engine's single open posture always constructs
`WatcherConfig` from `SqliteOpts`, ADR-023 §4; a second
config-less path would recreate the mixed-posture shape D-29
resolved). None changed kept-fidelity posture — all six are
`drop`-category entries against the *kept* set, with the affected
substrate tests re-expressing their properties through the
reachable surface (no assertion strength lost: the probe tests
test the same coercion/lease behavior through the surviving forms).
- **Two substrate items kept under `#[cfg(test)]`** rather than cut:
`SharedUpdateWatcher::subscriber_count` and the
`DEFAULT_WATCHER_POLL_INTERVAL` re-export — engine-side tests
reach them (the leak/no-leak pins, the 1 ms default pin); they are
test-observation surface, honestly gated `#[cfg(test)]`, not
suppressed. `open_store` was likewise promoted `pub(crate)` (the
store tests construct the concrete handle; `open` stays the
consumer surface).
- **The exemplar row had a real-engine sequencing defect — fixed
suite-side** (a suite-text change, ADR-017 §2 class 4): the
name-validation row held its `tx` handle alive across the whole
battery including the final `with_tx` leg. The mock harness never
saw this; a real engine's `begin_tx` parks a concurrent begin on
the writer slot (ADR-007's honest model), so the row deadlocked a
real factory. The tx battery is now scoped so the handle drops
before the `with_tx` leg. The row's *assertions* are unchanged —
only the sequencing fix — but the incident is the wave-5 lesson
the factory exists to surface: rows are mock-blind until an
executes them against a real single-writer engine.
- **Row set** (nine total — the exemplar + eight new, all in
`alkstore-contract-suite/src/properties.rs`, one owner,
version-stamped per the convention, each a public `pub async
fn(&dyn StoreFactory)`): the ADR-023-stamped rows (extent-clamp
including the boundary-totality legs, duration-refusal,
`encode_payload` round-trip), and the engine-scoped rows the task
names (PayloadTooLarge-never-produced — the SQLite arm, the pg
rejection arm rides wave 4's adoption of the same row text; the
drop=rollback no-ghosts; in-tx read-your-own-writes;
enqueue-opts resolution — ADR-020 §1–§3; receiver close/save arms
— ADR-021 §5). **Plain-path open (§3) and poll cadence (§4) pin
engine-side, not as suite rows**: both are constructor-level
SQLite-native facts not expressible over `StoreFactory::open()` —
`uri_shaped_open_path_is_a_literal_filename` and
`poll_interval_flows_to_the_watcher_config` (stamped,
`open_tests.rs`) are this engine's rows for them; wave 4's pg
column simply doesn't carry them (they're SQLite-scoped backlog
rows per core-contract.md).
- **The factory** (`alkstore-sqlite/tests/contract_suite.rs`): a fresh
never-before-used temp file per `open` under a per-instance
directory; teardown = directory delete, idempotent
(already-deleted ⇒ `Ok`). Its isolation/idempotence contract has
its own pin in the test target (`opens_are_isolated_and_teardown_is_idempotent`);
receiver-close rows drive the terminal-close arm by dropping the
store handle (the dispose carrier every engine has), not teardown —
deleting files under a live store is not a close mechanism.
- **Coverage spot-check** (cargo-llvm-cov, engine crate): 93.59%
lines / ~89% regions, every file ≥85% lines; the misses are error
arms and Windows-only `file_id` variants
(`watcher.rs`'s HighRes/LowRes halves) — no large uncovered regions
outside error arms, the gate the task pinned.
## Summary
> Landed: the two `#![allow]` lints removed from
> `substrate/mod.rs` (its module docs re-stated to the wave-3 wired
> posture); the removal surfaced six dead surfaces — cut, each
> registered D-32..D-36 in `PROVENANCE.md` (queue-side: `arg_opt_i64`,
> `now_unix`, `queue_next_claim_at`; writer/watcher-side:
> `Writer::try_acquire`, `UpdateWatcher::spawn`,
> `SharedUpdateWatcher::new`), their probe tests re-expressed through
> the reachable surface; two test-observation items honestly
> `#[cfg(test)]`-gated (`subscriber_count`, the
> `DEFAULT_WATCHER_POLL_INTERVAL` re-export); no allows re-added —
> clippy `-D warnings` green without them.
>
> Contract-suite adoption: eight new rows in
> `alkstore-contract-suite/src/properties.rs` (extent-clamp +
> boundary-totality, duration-refusal, payload round-trip,
> `PayloadTooLarge`-never-produced SQLite arm, drop=rollback
> no-ghosts, in-tx read-your-own-writes, enqueue-opts resolution,
> receiver close/save arms) — all version-stamped, all re-exported
> from the suite lib. `store::SqliteFactory` implemented in the
> engine's new integration test target
> (`alkstore-sqlite/tests/contract_suite.rs`), running all nine rows
> (the exemplar + the eight) against the SQLite factory — 10 tests,
> green; the factory's isolation/idempotence contract pinned
> alongside. Found and fixed suite-side: the exemplar row's
> hold-the-tx-across-`with_tx` sequencing deadlocked any real
> single-writer factory (the mock never saw it).
>
> Engine crate lib docs: the posture statements surfaced under a
> `# Posture` heading — single-host (ADR-016) and writer-parking
> (ADR-007's negative consequence) spelled as the crate's identity
> statements.
>
> Verified: workspace `cargo build`/`cargo test` green (25 + 186 +
> 10 + 3 + harness), clippy `--workspace --all-targets -D warnings`
> clean, `cargo fmt --check` clean; engine-crate coverage 93.59%
> lines (cargo-llvm-cov), misses confined to error arms and
> Windows-only watcher variants.