- src/mem.rs: MemBackend implements Backend (seven methods + put_staged, name "mem") over Arc<parking_lot::Mutex<BTreeMap<..>>>; CAS first-writer-wins puts, materializing MemCursor body, degenerate in-memory MemStaging whose commit publishes via the same CAS clause and self-discards on failure; discard leaves zero residue. - CAS re-put is dedup for both put forms; reads are no-ops on the virgin store; delete carries Missing; size is metadata-only. - Eight in-module tests mirror the wave-1 double's assertions: method contract, list well-formedness, cursor body read contract + ADR-006 range digest, empty-entry round-trip, staged happy path, and both hygiene forms (fail_commit test hook stands in for media failure). - backend.rs: clamped promoted pub(crate) — the shared EOF-clamping arithmetic both mem cursor bodies compose (no per-engine duplicate). Verification: cargo test --features mem (33+7 green); cargo test (default) green; clippy --all-features --all-targets -D warnings green; fmt --check green.
5.9 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| engine-mem | mem kv engine — the contract-reference engine | completed | narrow | low | component | implementation |
|
Description
Implement the mem kv-tier engine (feature mem; ADR-011 §2): a
BTreeMap-shaped ephemeral implementation of the kv tier's contract —
the first real engine, and the contract-reference engine: every
other engine's conformance rows mirror its column (store-api.md
invariant 7), so its bodies are the shapes the suite holds the rest to.
- Backend impl (
src/mem.rs, behind#[cfg(feature = "mem")]) against the wave-1 trait (src/backend.rs): the seven methods plusput_staged, opaque byte keys/values,name() -> "mem".put— CAS first-writer-wins (entry().or_insert()); a re-put of an existing key is a no-op, never an overwrite.get—Noneon absence (neverError::Missing); the cursor body is the materialized family (the whole value;len()from the stored value).put_staged— the degenerate in-memory stage (ADR-010 §1: kv bodies stage in memory and commit through the whole-value row write);appendextends the buffer,commitpublishes via the same CAS clause and self-discards on failure,discarddrops the buffer with zero residue.delete—Err(Error::Missing)when absent;list— complete and well-formed (the map's keys);size— trivially metadata-only (the stored value's length, no content fetch semantics to violate).- Virgin-store reads are no-ops (an empty map is the virgin store).
- Locking posture:
parking_lotfor the short-held map lock (AGENTS convention 3;unwrap_or_else(|e| e.into_inner())on poisoning). No blocking I/O exists here. - Unit tests in-module: the method contract (virgin-store no-ops, CAS re-put, Missing discipline, size exactness), the staged-put happy path and both hygiene forms (discard → zero residue; commit failure → self-discard) — mirroring the wave-1 test-double's assertions, now against the real engine.
The conformance column itself is suite-column-mem (separate task);
this task ships the engine and its in-module unit tests only.
Acceptance Criteria
src/mem.rsimplementsBackendcompletely (seven methods +put_staged) behind featuremem, with the materialized cursor body and the degenerate staging body- CAS first-writer-wins on both put forms; re-put never overwrites
- Stage hygiene holds in both forms (discard → zero residue; failed commit → self-discard), unit-tested
- Virgin-store reads are no-ops;
delete/absent-key discipline per the trait contract;sizemetadata-only cargo test --features memgreen;cargo clippy --all-features --all-targets -- -D warningsandcargo fmt --checkgreen
References
- docs/architecture/backends-and-dispatch.md (§kv tier — mem engine)
- docs/architecture/decisions/011-vocabulary-tiers-engines-and-fleet-state.md §2
- docs/architecture/decisions/010-backend-io-seams-and-fleet-state-home.md §1
- src/backend.rs (the trait + seam contracts this implements)
Notes
backend.rs'sclamped(already documented as "the shared EOF-clamping arithmetic of the cursor contract") was promotedpub(crate)so both mem cursor bodies compose it — no per-engine duplicate of the clamp.MemBackend/MemStagingarepub(crate)(the Backend trait is crate-internal per ADR-003's visibility design point); the module carries#![allow(dead_code)]mirroringbackend.rs's seam-scope pattern, which shrinks when dispatch names the mem engine.- parking_lot's
Mutexdoes not poison, so theunwrap_or_else(|e| e.into_inner())posture has nothing to apply to — plain short-held locks (AGENTS convention 3). - mem's
commitcannot fail in normal operation (no media). The wave-1 double'sfail_commitknob is carried as a#[cfg(test)]field on the backend/staging pair so the failure form's self-discard hygiene is exercised against the real engine; it stands in for the media-failure injection later engines need (the conformance suite's fault-hook story issuite-column-mem's concern). - Not fleet-valid (ADR-011 §4): no
gcengine-state implementation — confirmed SQL-engine-only in src/gc.rs.
Summary
Implemented the mem contract-reference engine (feature mem) in
src/mem.rs: MemBackend implements Backend completely (name mem;
has/get/put/put_staged/delete/list/size) over an
Arc<parking_lot::Mutex<BTreeMap<Vec<u8], Vec<u8>>>>. put is CAS
first-writer-wins (entry().or_insert_with()); get hands out
MemCursor, the materializing kv body (whole value, EOF-clamped reads,
len() from the stored value); put_staged hands out MemStaging, the
degenerate in-memory stage — append extends, commit publishes via the
same CAS clause (std::mem::take before the lock; losing the race is
dedup, never a failure) and self-discards on failure, discard drops the
buffer with zero residue. Reads are no-ops on the virgin store; delete
carries Missing; size is metadata-only.
Eight in-module unit tests mirror the wave-1 double's assertions against the real engine: the method contract (virgin no-ops, CAS re-put, Missing discipline, size exactness), list completeness/well-formedness, the materialized cursor body's read contract (EOF clamping, zero-length, and the ADR-006 read_range digest), the empty-entry round-trip, the staged happy path (verification pass over the staged whole through the read seam, then both re-put forms are dedup no-ops), and both hygiene forms (discard → zero residue; injected commit failure → self-discard).
Verification: cargo test --features mem green (33 unit + 7 integration),
cargo test (default) green, cargo clippy --all-features --all-targets -- -D warnings green, cargo fmt --check green.