Files
alkstore/tasks/mem-engine-scheduler-outbox.md
T
glm-5.3-flash 5abd351c86 Wave-6 decomposition (mem engine): eleven tasks per the pg-wave rhythm — foundations (crate scaffold, MemStore::new isolation, guarded state core, wake routing, wasm32 gate from birth), seam-tx (the load-bearing tx overlay: eleven staged _tx methods, commit-merge + wake-at-commit — pg-fix-tx-wake's discipline structural from the start, drop = discard trivial, with_tx panic posture), mechanisms mutually parallel (notify-listen close-at-engine-drop/no-replay/never-coalesced; queues = ADR-010 machine driver-free with the equal-jitter curve and opts resolution as ADR-012 §2's third owner; streams log+offsets+trim; locks TTL registry, no busy-path analog), scheduler-outbox (tick/catch-up-64/leadership through the __alkstore_scheduler lock, engine-uniform per ADR-009 §4; outbox over queues with the 60/5/5 seam stamp), integration (suite third StoreFactory column green on host under a current-thread flavor, wasm32 acceptance items, engine-mem.md to implementation-complete), and the review-wave-6 gate (born-pinned audit: conformance read, discharge-map wiring, wasm items, three-way equivalence green, class-1 window discipline). Window riders: suite-harness-current-thread — the wave's one suite-side pre-task, past_stamp_sleep's blocking sleep goes async per review 003's properties.rs:1683 posture note, enabling the current-thread flavor; pg-fix-scheduler-tick-seam — review 003 Finding 1, the cfg(test) transient-fault seam driving the real tick_with_retries through retry-then-success and exhaustion arms (the last uncovered wave-4 hardening arm, sqlite-commit-error-arm pattern). Task hygiene: pg-fix-open-path frontmatter fixed (unquoted 'max_size: 0' colon-space inside the name scalar broke YAML parsing — taskgraph validate had been red one-error since the wave-4 fix-batch decomposition; also restores review-wave-4-fixes' dependency resolution). implementation.md: wave-6 table row → decomposed, task-set listing with the parallelism note (rider + pre-task independent of the mem chain; rider closes before the gate), wave-6 decomposition bullet in the review-rounds record. Docs-only change; verified taskgraph validate (60 tasks, no cycles), cargo fmt --check, cross-reference read
2026-10-10 09:57:01 +00:00

3.8 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
mem-engine-scheduler-outbox Mem engine — scheduler (`schedule`/`unschedule`/`run_schedules`) and outbox helper pending
mem-engine-queues
mem-engine-locks
moderate medium component implementation
wave-6
mem-engine
scheduler
outbox

Description

The collapsed scheduler and the outbox helper (ADR-009, ADR-014):

  • Scheduler surface: schedule(name, spec, queue, payload, opts) (upsert by name; both name-bearing arguments validated — schedule name and queue argument identically, InvalidName/ReservedName), unschedule(name) -> bool, and the opt-in run_schedules(stop: StopToken) runner over a mem-owned tick task.
  • Tick machinery — engine-uniform (ADR-009 §4's rule; single-instance leadership is trivially owned but the machinery still runs): each boundary fire enqueues ordinary work stamped with the schedule's ScheduleOpts resolved over the target queue's derived engine defaults; fire+advance is atomic under the guarded state (the no-double-fire floor); bounded catch-up with the fixed 64-boundary cap and skip-forward past the cap (mem-owned tick implementation — third owner per ADR-012 §2); leadership rides the reserved __alkstore_scheduler lock through the lock mechanism (so two runners on one instance contend through the same machinery the other engines use; loss → Err(LeadershipLost), clean stop → Ok(())).
  • Spec grammar v1: @every <n><unit> (s|m|h|d) only — mem owns its parser (third copy, the grammar is small and pinned); cron strings rejected (InvalidSpec). Boundary waits ride tokio time.
  • Outbox helper: Outbox { enqueue, run_once } per ADR-019 §5 — run_once(worker_id, delivery) -> bool is pull: claim one, ack on Ok, retry(err, None) on Err; no engine-issued heartbeat inside delivery (inherited posture); outbox_enqueue_tx staged in the overlay by mem-engine-seam-tx (the 60/5/5 stamp set); the derived backing queue __alkstore_outbox:{outbox} unreachable by enqueue_tx (validation already pins the reserved prefix), name format pinned identical to the other engines (the suite's derived-queue-naming row composes it).

Unit tests pin: boundary fires (deterministic, tokio-time driven), bounded catch-up + skip-forward, leadership lock contention/loss through two run_schedules calls, outbox run_once ack/retry shapes, derived-name format.

Acceptance Criteria

  • Scheduler surface + tick: boundary fire, catch-up (≤64), skip-forward — unit-pinned with tokio-time determinism
  • Leadership contention through the __alkstore_scheduler lock; LeadershipLost on loss, Ok(()) on clean stop — pinned
  • Schedule name + queue argument validation; @every-only parser (cron → InvalidSpec) — pinned
  • Outbox: enqueue/run_once semantics (no engine heartbeat); derived backing-queue name format identical to both engines — pinned
  • cargo check --target wasm32-unknown-unknown -p alkstore-mem clean; workspace gates green

References

  • docs/architecture/queues.md; core-contract.md §scheduler, §outbox
  • docs/architecture/decisions/009-scheduler-collapse.md §1/§3/§4/§6; 014-outbox-tx-enqueue.md; 019 §4/§5; 020 §3
  • docs/architecture/engine-mem.md §Mapping the contract (scheduler/outbox row)
  • tasks/pg-engine-scheduler-outbox.md (the structural twin's task of record — tick/catch-up/leadership shapes)

Notes

To be filled by implementation agent

Summary

To be filled on completion