87 lines
3.8 KiB
Markdown
87 lines
3.8 KiB
Markdown
---
|
|
id: mem-engine-scheduler-outbox
|
|
name: Mem engine — scheduler (`schedule`/`unschedule`/`run_schedules`) and outbox helper
|
|
status: pending
|
|
depends_on: [mem-engine-queues, mem-engine-locks]
|
|
scope: moderate
|
|
risk: medium
|
|
impact: component
|
|
level: implementation
|
|
tags: [wave-6, mem-engine, scheduler, outbox]
|
|
---
|
|
|
|
## Description
|
|
|
|
The collapsed scheduler and the outbox helper
|
|
([ADR-009](../architecture/decisions/009-scheduler-collapse.md),
|
|
[ADR-014](../architecture/decisions/014-outbox-tx-enqueue.md)):
|
|
|
|
- **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](../architecture/decisions/009-scheduler-collapse.md)
|
|
§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](../architecture/decisions/012-forked-substrate-design.md)
|
|
§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](../architecture/decisions/019-mechanism-handle-surfaces.md)
|
|
§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 |