Files
alkblobs/tasks/engine-mem.md
T
glm-5.3-flash 0b43ea1449 feat(engines): the mem contract-reference engine — first real engine (wave 2)
- 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.
2026-10-11 21:56:29 +00:00

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
wave-2
engines
mem

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 plus put_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 — None on absence (never Error::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); append extends the buffer, commit publishes via the same CAS clause and self-discards on failure, discard drops 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_lot for 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.rs implements Backend completely (seven methods + put_staged) behind feature mem, 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; size metadata-only
  • cargo test --features mem green; cargo clippy --all-features --all-targets -- -D warnings and cargo fmt --check green

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's clamped (already documented as "the shared EOF-clamping arithmetic of the cursor contract") was promoted pub(crate) so both mem cursor bodies compose it — no per-engine duplicate of the clamp.
  • MemBackend/MemStaging are pub(crate) (the Backend trait is crate-internal per ADR-003's visibility design point); the module carries #![allow(dead_code)] mirroring backend.rs's seam-scope pattern, which shrinks when dispatch names the mem engine.
  • parking_lot's Mutex does not poison, so the unwrap_or_else(|e| e.into_inner()) posture has nothing to apply to — plain short-held locks (AGENTS convention 3).
  • mem's commit cannot fail in normal operation (no media). The wave-1 double's fail_commit knob 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 is suite-column-mem's concern).
  • Not fleet-valid (ADR-011 §4): no gc engine-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.