The queue mechanism (ADR-010 state machine over the in-memory job table, mem's third-owner equal-jitter curve + opts resolution) already landed implemented with the seam task's whole-engine scope (mem-engine-seam-tx Note 1); this task's work, per the disposition the notify/listen twin recorded, was reconciling the description's pin list against the existing suite and adding the missing engine-side unit pins — no production code changed, the realization verified correct as-found. Already pinned by the seam task (reconciled, recorded in Notes): lifecycle + stamps + resolved get_job values, claim ordering, extent clamps at entry, worker-id validation, the uniform validity predicate, late-heartbeat refusal + absolute-reset renewal, reclaim-eats-attempt + loser-ack-refuses, the pinned dead-letter default strings, dead-row get_job visibility, both-states sweep + retention + scoping, the tx stamp shapes, and the resolution legs + base-5 curve range/cap/spread. Added (6): the in-process claim-race atomicity pin (8 concurrent workers over 4 rows — every row handed exactly once through the guarded section, the description's claim-vs-claim bullet); the claim-vs-expiry boundary determinism pin (at now == deadline: the d < now reclaim predicate and the d >= now holder-op predicate are coherent — no reclaim, heartbeat/ack still valid; one second past: reclaimable with its attempt consumed; lapsed ids silently uncounted by ack_batch); the engine-side mirror of the suite's backoff_curve_equivalence row — base 2 s at [1,2]/[2,4]/[4,8] driven end-to-end through claim -> retry(None) -> get_job's run_at with the Some(5)-verbatim and Some(0)-ready-now override legs, exact under the frozen clock — both through the handle and pinned at backoff_delay_s itself (the cap leg stays in resolution.rs's base-5 pins per suite-opts-backoff-rows' recorded disposition); the D-12 pre-claim sweep pin (a lapsed row with its budget spent claims nothing and dead-letters with the exhaust string at the next claim, never strands); and unconditional cancel across both states (the holder's post-cancel ack refusing — the not-an-interrupt honesty). One test-authoring note recorded: heartbeat's absolute reset moves the deadline, so boundary legs stage on fresh rows to keep each observation exact. Task file: status completed, Notes (the seam-carried disposition + reconciliation inventory + the six adds + the heartbeat-observation note) + Summary filled. Verified: cargo test -p alkstore-mem 97/97 (91 + 6 new; new tests green solo x3), workspace cargo test green (core 25, suite-harness 3, mem 97, pg 124+25+9, SQLite 191+25), clippy --all-targets -D warnings clean, cargo fmt --check clean, cargo check --target wasm32-unknown-unknown -p alkstore-mem clean
9.8 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| mem-engine-queues | Mem engine — queues (in-memory job table, ADR-010 state machine, engine-owned backoff curve) | completed |
|
moderate | medium | component | implementation |
|
Description
The queue mechanism: the ADR-010 state machine realized over an in-memory job table — all driver-free.
Queuehandle surface (ADR-019 §1):enqueue(auto-commit, resolving over the handle's opts),claim_one/claim_batch(extents:n <= 0claims nothing),ack_batch(per-id uniform predicate, lapsed/non-claimed silently not counted),cancel(unconditional delete),get_job, and the queue-scopedsweep_expired(no-stranded-rows: every past-expiry row in any state moves to dead + retention enforcement).- Claim discipline: exactly-once handout,
worker_idclaimant identity (non-empty), claim ordering priority DESC → ready-time → enqueue FIFO. Visibility expiry and reclaim — reclaim consumes an attempt; the dual-execution window is contract-honest (a worker past its deadline may complete its work but its ack will not land). Under a single engine instance the claim race is in-process — the guarded merge discipline must still make claim-vs-claim atomic and claim-vs-expiry deterministic at the row level. - JobHandle ops (ADR-019
§3):
ack/retry/failone-shot terminal,heartbeat(&self)repeatable absolute-reset renewal; the uniform validity predicate (processing + unexpired deadline); deadline lapse refuses all ops, false not error.retry(err, None)computes the queue's equal-jitter exponential delay — mem's own implementation (ADR-012 §2's one-owner rule, third owner; the SQLite engine'sresolution.rsis reference, not a dependency);retry(err, Some(d))overrides verbatim;fail= immediate dead-letter with the engine-default strings ("failed"/"max attempts exceeded"). - Opts stamping (ADR-020):
resolution rules (delay-over-
run_at, relativeexpires) are mem-owned (third copy); handle-enqueue stamps the handle's opts; the tx/no-handle shapes stamped plain 300/3/5/none inmem-engine-seam-tx.get_jobshows resolved values. - Dead letters: move-to-dead storage,
get_jobsees dead rows (last_error/died_at),dead_letter_retention_s(None = forever) enforced bysweep_expired. No redrive API. - Timestamps and expiry checks are tokio-time/clock reads against the
state core's clock accessor; expiry is checked at claim/renew
boundaries (no ambient sweeper —
sweep_expiredis caller-driven, cadence recipe unchanged).
Acceptance Criteria
- Full
Queue/JobHandlesurfaces over the in-memory job table - The ADR-010 state machine properties unit-pinned: visibility reclaim consumes an attempt, dead-letter moves, no-stranded-rows sweep, handle-op validity predicate, late-heartbeat boundary
- Equal-jitter curve + opts resolution pinned to the identical numeric behavior the suite's equivalence rows assert (per the engine-side pin posture used for the cap legs)
- Numeric-domain guards (extents) at entry — pinned
cargo check --target wasm32-unknown-unknown -p alkstore-memclean; workspace gates green
References
- docs/architecture/queues.md; core-contract.md §queues
- docs/architecture/decisions/010-queue-semantics-depth.md; 019-mechanism-handle-surfaces.md §1/§3; 020 §1–§3; 023 §2
- docs/architecture/engine-mem.md §Mapping the contract (queues row)
- tasks/pg-engine-queues.md (the structural twin's task of record — the wave-4 rhythm and the resolution rule set)
Notes
Filled by implementation agent, 2026-10-10.
- The implementation already landed in the seam task —
mem-engine-seam-txNote 1 records that the mem engine's fullStoresurface (including theMemQueueHandle/MemJobHandlemechanism inalkstore-mem/src/queue.rsand mem's third-ownerresolution.rsarithmetic) is all-or-nothing per trait impl, so this task found its mechanism implemented. Its work was the coverage reconciliation against the description's pin list plus the missing engine-side unit pins — the same disposition the notify/listen twin task recorded (mem-engine-notify-listenNotes 1–3). - Coverage reconciliation: already pinned by the seam task's
suite in
queue.rs/resolution.rs/tx.rs— the full lifecycle + stamp resolutions (300/3/5/none + per-job override, resolved values shown byget_job), claim ordering (priority DESC → ready-time ASC → id ASC), extent clamps (n = 0/n < 0→ empty at the entry, before any effect), empty-worker_idrejection, the uniform validity predicate (lapse refuses all ops, refusals leave the row intact), late-heartbeat refusal + absolute-reset renewal (withclaimed_at/attemptsuntouched), reclaim-consumes-an- attempt + the loser's ack refusing (the dual-execution honesty), retry/fail default strings ("max attempts exceeded"/"failed")- caller strings via the exhaust path, dead-row
get_jobvisibility withlast_error/died_at, the both-states no-stranded-rows sweep + retention (incl. forever-None) + queue scoping, the tx/no-handle stamp shapes (plain 300/3/5/none, outbox 60/5/5 intx.rs), and the resolution legs (delay-wins- over-run_at,run_atliteral, neither→now, negative-delay total, relative-expires) + the base-5 curve range/cap/spread pins inresolution.rs.
- caller strings via the exhaust path, dead-row
- What this task added — the six unpinned shapes: (a)
concurrent_claims_hand_out_work_exactly_once(8 racing workers over 4 rows via spawnedclaim_batchhandles: every row exactly once — the guarded-section claim-vs-claim atomicity pin the description's "claim race is in-process" bullet asks for); (b)claim_vs_expiry_is_deterministic_at_the_row_boundary(atnow == claim_expires_at: no reclaim (d < nowfalse), the holder's heartbeat/ack still valid (d >= now) — the two predicates' boundary coherence; one second past: reclaimable with its attempt consumed; the lapsed id silently uncounted byack_batch); (c)the_equal_jitter_curve_mirrors_the_suite_rows_ numeric_bounds(base 2,max_attempts7 — the suite row's own shape: three claim→retry(None)cycles asserting [1,2]/[2,4]/[4,8] read back throughget_job'srun_at, exact under the frozen clock; plus the override legsSome(5)verbatim andSome(0)ready-now per the boundary-total rule) — the engine-side pin of AC3's "identical numeric behavior"; the cap leg stays pinned inresolution.rs's base-5 tests persuite-opts-backoff-rows's recorded disposition; (d)backoff_base_two_lands_in_the_suite_ rows_exact_boundsinresolution.rs— the same base-2 bounds at the arithmetic function itself; (e)the_pre_claim_sweep_dead_ letters_exhausted_reclaimables(the D-12 shape: a lapsed row with its budget spent claims nothing and dead-letters with the exhaust string at the next claim — never strands claimable); (f)cancel_is_unconditional_across_states(pending + processing deleted, row-lessOk(false), the holder's post-cancel ack refusing — the not-an-interrupt honesty). - No production code changed — the seam task's realization was
verified correct as-found; this task is tests only (+5 in
queue.rs, +1 inresolution.rs, 97 mem tests total). One test-authoring note:heartbeat's absolute reset moves the deadline (now + extend), so a boundary-reclaim leg staged after a heartbeat on the same row reads the shifted deadline — the boundary test stages its legs on fresh rows to keep each observation exact.
Summary
Filled on completion, 2026-10-10.
Completed the mem engine's queues task against the seam task's
foundation: reconciled the description's pin list against
alkstore-mem/src/queue.rs + resolution.rs + tx.rs's existing
suite (13 pre-existing queue mechanism tests + the resolution and tx
stamp pins), found the full Queue/JobHandle surfaces and nearly
all ADR-010 properties already pinned, and added the six gaps: the
in-process claim-race atomicity pin (8 concurrent workers, exact-once
handout over the guarded section), the claim-vs-expiry boundary
determinism pin (the d < now / d >= now predicates' edge-second
coherence + the lapsed ack_batch non-count), the engine-side mirror
of the suite's backoff_curve_equivalence row (base 2 → [1,2]/[2,4]/
[4,8] end-to-end through claim→retry(None)→get_job.run_at with
the Some(5)/Some(0) override legs, and the same bounds pinned at
backoff_delay_s itself; the 1-hour cap stays in resolution.rs's
base-5 pins per the recorded suite disposition), the D-12 pre-claim
exhausted-reclaimable dead-letter sweep, and the both-states
unconditional cancel. Acceptance criteria: full surfaces ✓ (seam
task, lifecycle test), ADR-010 properties ✓ (seam tests + the new
boundary/reclaim/sweep pins), curve + opts resolution numeric
equivalence ✓ (new base-2 pins), extent guards ✓ (seam clamp test),
gates ✓. Verified: cargo test -p alkstore-mem 97/97 (91 + 6 new,
new tests green solo ×3), workspace cargo test green (core 25,
suite-harness 3, mem 97, pg 124+25+9, SQLite 191+25),
cargo clippy --all-targets -- -D warnings clean, cargo fmt --check
clean, cargo check --target wasm32-unknown-unknown -p alkstore-mem
clean — the wave-6 wasm gate stays green.