From f2f5e03d7cd202c224b58894ac3a254e81820720 Mon Sep 17 00:00:00 2001 From: "glm-5.3-flash" Date: Sun, 11 Oct 2026 14:56:40 +0000 Subject: [PATCH] docs(mem): pin growth postures and outbox delivered-or-reclaimable semantic Review 004 items 10+11: the two recorded mem growth postures (subscribe backlog drain unbounded on the consumer side; O(live-rows) claim scan with full-row clones) and the outbox's 'processed means delivered-or-reclaimable' semantic, pinned in engine-mem.md. The debug_assert arm was declined: the dropped ack/retry booleans also refuse benignly on legitimate in-closure handle ops, so it cannot separate a visibility lapse from a deliberate first-party outcome. --- docs/architecture/engine-mem.md | 52 +++++++++++++++++++++++----- tasks/mem-doc-growth-outbox-notes.md | 36 +++++++++++++++++-- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/docs/architecture/engine-mem.md b/docs/architecture/engine-mem.md index b2731bc..4ed76e1 100644 --- a/docs/architecture/engine-mem.md +++ b/docs/architecture/engine-mem.md @@ -1,13 +1,14 @@ --- status: stable -last_updated: "2026-10-10 (the wave-6 review gate passed: the -conformance read clean — three edge-domain fixes landed inline (the -stream cursor read's `i64::MAX` overflow, `trim_to`'s horizon -endpoint, the scheduler register-time interval overflow now rejecting -with `InvalidSpec` like the SQLite register) plus scaffold-residue -cleanup; the third column's 25-row set green under the current-thread -flavor; the wasm32 gate + feature subset verified; the rider's arms -verified)" +last_updated: "2026-10-11 (review-004 items 10+11 pinned: the growth +postures section — subscribe backlog drain, O(live-rows) claim scan — +and the outbox's delivered-or-reclaimable semantic; the wave-6 +review gate had passed earlier — conformance read clean, three +edge-domain fixes landed inline (the stream cursor read's `i64::MAX` +overflow, `trim_to`'s horizon endpoint, the scheduler register-time +interval overflow now rejecting with `InvalidSpec`), the third +column's 25-row set green under the current-thread flavor, the +wasm32 gate + feature subset verified, the rider's arms verified)" --- # Mem engine @@ -98,6 +99,23 @@ private to the caller's handle. | begin_tx | overlay allocation ([ADR-007](decisions/007-transactional-seam.md)) | | handle ops | direct `.await`s on guarded state; `encode_payload` via core (ADR-020 §4) | +### Outbox semantics + +The outbox is a helper over queues ([ADR-014](decisions/014-outbox-tx-enqueue.md)): +`run_once` claims one job through the ordinary claim machinery and +applies the outcome when delivery returns — `Ok` ⇒ ack, `Err` ⇒ +retry on the queue's own curve. The ack/retry application's +row-ref booleans are dropped: a delivery that outlived its +visibility window (or a consumer side-effect that handled the row +first, e.g. an in-closure `ack`/`retry` on the boxed handle) leaves +the outer outcome unapplied, and `run_once` still reports `true`. +Inherent to the no-heartbeat outbox design — at-least-once reclaim +is the recovery, not a second report. **Processed means +delivered-or-reclaimable**: `true` attests the claim was processed, +not that the ack/exhaust landed; renewal inside the window is the +consumer's obligation ([ADR-019](decisions/019-mechanism-handle-surfaces.md) +§5) and reclaim closes a lapsed one. + ## Asymmetry classification (ADR-024 §3) | Asymmetry | Mem posture | @@ -107,6 +125,24 @@ private to the caller's handle. | Receiver close | one close path: engine drop closes open receivers (process exit/shutdown); contract close-arm shapes apply unchanged ([ADR-021](decisions/021-tx-reads-and-value-shape-fixes.md)) | | Wake coalescing | not applicable — direct at-commit delivery, per-subscriber FIFO; the engine spec line above pins it | +## Growth postures (review 004 items 10–11) + +Two perf/posture notes recorded at the pre-release general review +(the mem side of [deployment.md](deployment.md)'s accepted growth +families), pinned here as the code-level economics: + +- **Subscribe backlog drain** — the subscribe path drains the full + event backlog into the receiver's pending deque *before the first + yield*, and pending keeps growing at publish rate while a consumer + is stalled (`alkstore-mem/src/stream.rs:314-331` — the documented + "drains to the tail then parks" shape, unbounded on the consumer + side). The feed ends at engine drop; `trim_to` bounds the stored + log, not a stalled consumer's pending deque. +- **Claim scan** — the claim path is an O(total-live-rows) scan with + full-row clones per claim (`alkstore-mem/src/queue.rs:122-181`) — + blessed economics for the ephemeral tier ([ADR-024](decisions/024-mem-engine.md) + §2). + ## Isolation and the suite factory Each `MemStore::new()` yields a distinct engine instance sharing diff --git a/tasks/mem-doc-growth-outbox-notes.md b/tasks/mem-doc-growth-outbox-notes.md index bc16e78..3bf8313 100644 --- a/tasks/mem-doc-growth-outbox-notes.md +++ b/tasks/mem-doc-growth-outbox-notes.md @@ -1,7 +1,7 @@ --- id: mem-doc-growth-outbox-notes name: Pin mem's growth postures and outbox semantics in the spec (review 004 items 10+11) -status: pending +status: completed depends_on: [] scope: narrow risk: trivial @@ -60,8 +60,38 @@ Doc-only plus at most one `debug_assert!` — no behavioral change. ## Notes -> To be filled by implementation agent +- Neither `engine-mem.md` growth nor outbox section existed — both + were added (the review's "carry into the growth section" assumed a + touch that creates them). Growth postures placed after the + asymmetry-classification table; the outbox semantic as a + `### Outbox semantics` subsection under "Mapping the contract" + (the table's scheduler/outbox row pointed there). +- The `debug_assert!` was **not** added (implementer's call, either + was offered): a debug assertion that the dropped ack/retry + booleans landed would also fire on legitimate in-closure handle + ops — a delivery closure that calls `ack`/`retry`/`fail` on the + boxed `JobHandle` (all available per ADR-019) makes the outer + `ack_row`/`retry_row` refuse benignly, so the assertion would + false-positive on valid flows and cannot distinguish a visibility + lapse from a deliberate first-party outcome without re-reading the + row's state (noise > value, debug-only). The doc sentence carries + the semantic; it also names the in-closure-op case the assertion + could not have separated. ## Summary -> To be filled on completion \ No newline at end of file +Doc-only change, no behavioral code. `docs/architecture/engine-mem.md` +gained: a `### Outbox semantics` subsection pinning "processed means +delivered-or-reclaimable" for the no-heartbeat outbox (`run_once` +returns `true` even when the ack/retry application refuses — at-least-once +reclaim is the recovery), and a `## Growth postures (review 004 items +10–11)` section with the two recorded postures anchored to +`stream.rs:314-331` (subscribe drains the full backlog into pending +before the first yield; pending grows at publish rate for a stalled +consumer) and `queue.rs:122-181` (O(total-live-rows) claim scan with +full-row clones — blessed ephemeral-tier economics). Frontmatter +`last_updated` refreshed. Verified: `RUSTDOCFLAGS="-D warnings" cargo +doc --no-deps` clean; `cargo test -p alkstore-mem` green (102 unit + +26 suite + 1 doctest — outbox tests exercise the pinned `run_once` +arms); `cargo clippy -p alkstore-mem --all-targets -- -D warnings` +and `cargo fmt --check` clean. \ No newline at end of file