--- id: mem-engine-queues name: Mem engine — queues (in-memory job table, ADR-010 state machine, engine-owned backoff curve) status: pending 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 - [ ] Full `Queue`/`JobHandle` surfaces 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-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 > To be filled by implementation agent ## Summary > To be filled on completion