Files
alkstore/tasks/mem-engine-queues.md
T
glm-5.3-flash 61a1148165 mem engine queues — the wave-6 mechanism task lands: coverage reconciliation against the seam task's foundation, with the six unpinned engine-side pins (mem-engine-queues)
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
2026-10-10 12:15:04 +00:00

178 lines
9.8 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: mem-engine-queues
name: Mem engine — queues (in-memory job table, ADR-010 state machine, engine-owned backoff curve)
status: completed
depends_on: [mem-engine-seam-tx, mem-engine-notify-listen]
scope: moderate
risk: medium
impact: component
level: implementation
tags: [wave-6, mem-engine, queues]
---
## Description
The queue mechanism: the
[ADR-010](../architecture/decisions/010-queue-semantics-depth.md) state
machine realized over an in-memory job table — all driver-free.
- **`Queue` handle surface** ([ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)
§1): `enqueue` (auto-commit, resolving over the handle's opts),
`claim_one`/`claim_batch` (extents: `n <= 0` claims nothing),
`ack_batch` (per-id uniform predicate, lapsed/non-claimed silently
not counted), `cancel` (unconditional delete), `get_job`, and the
queue-scoped `sweep_expired` (no-stranded-rows: *every* past-expiry
row in any state moves to dead + retention enforcement).
- **Claim discipline**: exactly-once handout, `worker_id` claimant
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](../architecture/decisions/019-mechanism-handle-surfaces.md)
§3): `ack`/`retry`/`fail` one-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](../architecture/decisions/012-forked-substrate-design.md)
§2's one-owner rule, third owner; the SQLite engine's `resolution.rs`
is 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](../architecture/decisions/020-enqueue-opt-semantics-and-bridges.md)):
resolution rules (delay-over-`run_at`, relative `expires`) are
mem-owned (third copy); handle-enqueue stamps the handle's opts;
the tx/no-handle shapes stamped plain 300/3/5/none in
`mem-engine-seam-tx`. `get_job` shows resolved values.
- **Dead letters**: move-to-dead storage, `get_job` sees dead rows
(`last_error`/`died_at`), `dead_letter_retention_s` (None = forever)
enforced by `sweep_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_expired` is caller-driven,
cadence recipe unchanged).
## Acceptance Criteria
- [x] Full `Queue`/`JobHandle` surfaces over the in-memory job table
- [x] 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
- [x] 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)
- [x] Numeric-domain guards (extents) at entry — pinned
- [x] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
clean; 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.
1. **The implementation already landed in the seam task** —
`mem-engine-seam-tx` Note 1 records that the mem engine's full
`Store` surface (including the `MemQueueHandle`/`MemJobHandle`
mechanism in `alkstore-mem/src/queue.rs` and mem's third-owner
`resolution.rs` arithmetic) 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-listen`
Notes 1–3).
2. **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 by `get_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_id` rejection, the
uniform validity predicate (lapse refuses all ops, refusals leave
the row intact), late-heartbeat refusal + absolute-reset renewal
(with `claimed_at`/`attempts` untouched), 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_job`
visibility with `last_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 in `tx.rs`), and the resolution legs (delay-wins-
over-`run_at`, `run_at` literal, neither→now, negative-delay total,
relative-`expires`) + the base-5 curve range/cap/spread pins in
`resolution.rs`.
3. **What this task added** — the six unpinned shapes: (a)
`concurrent_claims_hand_out_work_exactly_once` (8 racing workers
over 4 rows via spawned `claim_batch` handles: 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` (at
`now == claim_expires_at`: no reclaim (`d < now` false), 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 by
`ack_batch`); (c) `the_equal_jitter_curve_mirrors_the_suite_rows_
numeric_bounds` (base 2, `max_attempts` 7 — the suite row's own
shape: three claim→`retry(None)` cycles asserting [1,2]/[2,4]/[4,8]
read back through `get_job`'s `run_at`, exact under the frozen
clock; plus the override legs `Some(5)` verbatim and `Some(0)`
ready-now per the boundary-total rule) — the engine-side pin of
AC3's "identical numeric behavior"; the cap leg stays pinned in
`resolution.rs`'s base-5 tests per `suite-opts-backoff-rows`'s
recorded disposition; (d) `backoff_base_two_lands_in_the_suite_
rows_exact_bounds` in `resolution.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-less `Ok(false)`, the holder's post-cancel ack
refusing — the not-an-interrupt honesty).
4. **No production code changed** — the seam task's realization was
verified correct as-found; this task is tests only (+5 in
`queue.rs`, +1 in `resolution.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.