--- id: mem-engine-locks name: Mem engine — named locks (in-memory TTL registry) status: completed depends_on: [mem-engine-seam-tx] scope: narrow risk: low impact: component level: implementation tags: [wave-6, mem-engine, locks] --- ## Description The named-locks mechanism over an in-memory TTL registry (engine-mem.md §Mapping the contract, locks row): - `store.try_lock(name, owner, ttl)` — acquire or fail (`Option `; no-work is a value); validation at entry (empty → `InvalidName`, reserved → `ReservedName`); **duration guard at entry** — `ttl <= 0` rejects with opaque `Err` ([ADR-023](../architecture/decisions/023-fourth-review-round.md) §2, durations kind), never a silent immediately-expired lease. - **`Lock` handle** ([ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)): `renew(ttl)` (absolute reset; renews past expiry refused) and `release`. Registry entries carry owner + deadline; expiry is a clock check at try/renew boundaries (tokio time; no ambient revoker) — after TTL expiry exclusion lapses *silently* (the ADR-008 §7 row), re-acquirable; the holder may still release. - **Single-instance contention semantics**: two `try_lock`s on the same name within the registry are serialized by the guarded-state discipline — first wins, second gets `None` cleanly (the SQLite busy-path question has no mem analog; loser is a value, never an error). Not part of the tx seam (no `lock_tx` — contract-verbatim: a lock held across a business tx is held by explicit acquisition; the overlay neither sees nor stages locks). ## Acceptance Criteria - [x] `try_lock`/`renew`/`release` over the TTL registry; entry validation (names + duration guard) — pinned - [x] TTL expiry: silent lapse, re-acquisition, renew-past-expiry refused — pinned (clock-controlled tests via the state core's clock accessor) - [x] Concurrent-contention shape: loser is `None`, winner's lease intact — pinned - [x] `cargo check --target wasm32-unknown-unknown -p alkstore-mem` clean; workspace gates green ## References - docs/architecture/core-contract.md §named locks - docs/architecture/decisions/008-contract-v1-pinning.md §7; 019-mechanism-handle-surfaces.md; 023 §2 - docs/architecture/engine-mem.md §Mapping the contract (locks row) - tasks/pg-engine-locks.md (the structural twin's task of record — the duration guards land identically) ## Notes > Filled by implementation agent, 2026-10-10. 1. **The implementation already landed in the seam task** — `mem-engine-seam-tx` Note 1 (the all-or-nothing trait-impl disposition, the same one the notify-listen and queues twins recorded): the `MemLock` registry mechanism in `alkstore-mem/src/lock.rs` was implemented with the seam's whole-engine scope; this task found its mechanism *implemented*. 2. **Full coverage reconciliation — zero new tests needed**: every shape the description and the three acceptance criteria enumerate was already pinned by the seam suite in `lock.rs`: the contention shape (first wins, loser `None` as a clean value, same-owner re-grant without a second lease row — `contention_grants_once_and_ the_loser_reads_none`), the duration guard (`ttl <= 0` → opaque `Database` `Err` on both `try_lock` and `renew`, ADR-023 §2's durations kind — `duration_guards_reject_non_positive_ttls`), the TTL expiry row via the frozen clock (in-TTL refusal, silent lapse, re-acquisition, old-holder renew refused — `expiry_lapses_silently_ and_reacquires`), renew-past-expiry refused + the new holder's clean life (`renew_past_expiry_is_refused`), the release shapes (held-true, past-expiry-still-the-holder's, re-acquired-elsewhere no-op — `release_shapes`), entry validation (empty/blank/reserved name, empty owner — `entry_validation`), and the locks-are-not-tx-scoped posture (the overlay neither sees nor stages locks — `locks_are_not_tx_scoped`). Note also the seam task's recorded semantis delta (seam Notes 7): mem pins renew-past-expiry *refused*, where the SQLite substrate would revive a not-yet-purged lapsed row — the stricter, contract-honest arm. 3. **No production code changed and no test changed** — the task is a disposition: the surface was verified correct as-found. ## Summary > Filled on completion, 2026-10-10. Completed the mem engine's locks task as a pure reconciliation: the TTL-registry mechanism landed with the seam task's whole-engine scope, and the reconciliation against the description's pin list found all three acceptance criteria's shapes already unit-pinned in `alkstore-mem/src/lock.rs`'s seven tests (contention/loser-None, duration guards on both entry kinds, clock-controlled silent lapse + re-acquisition + renew-past-expiry refused, release shapes, entry validation, no-`lock_tx`). No code and no tests changed; acceptance criteria satisfied as-found. Verified: `cargo test -p alkstore-mem` green, workspace `cargo test` green, `cargo clippy --all-targets -- -D warnings` clean, `cargo fmt --check` clean, `cargo check --target wasm32-unknown-unknown -p alkstore-mem` clean.