From a gap analysis against NestJS and AdonisJS.
Nest ships @nestjs/schedule; there is no equivalent here, and a cron/scheduler deployment is one of the most common process kinds a backend needs.
It is the cleanest fit for thesis #1 of any missing feature. "One process, one runtime" already says an api, a consumer and a worker are three deployments of the same module under different runtimes — a scheduler is simply the fourth. Everything the kernel asks of a runtime is already answerable for it:
- A unit per tick.
RunUnit already exists; a tick is a natural unit, with the schedule entry's name as UnitMeta.id and a minted traceId per firing (per the second contract a runtime owes — a schedule name is a category, not a unique id, which is exactly the trap that contract documents).
Serving.drain. Stop firing new ticks, wait for in-flight ones, honour the kernel's deadline signal. Simpler than @btravstack/temporal's, which already solves the harder version of this.
Serving.info. The schedule, so an operator can read back what this process actually runs — the same way AmqpInfo derives queues from the contract rather than from an option that could disagree.
Design questions worth settling in the issue rather than in code: whether schedules are declared as a contract (like the other three starters) or as options; whether a missed tick is skipped or caught up; and whether multi-replica coordination is in scope at all, or explicitly left to the application (a leader-election port, or "run one replica").
Acceptance
- A
@btravstack/scheduler starter providing a SchedulerRuntime over core's RuntimePort, with needs: [] like the other three.
- One kernel unit per tick, with a unique
traceId per firing.
drain stops scheduling and waits for in-flight ticks, released at the kernel's deadline.
- A stated answer on missed ticks and on multi-replica behaviour, even if the answer is "not our problem".
- An example workspace, since
examples/ is part of the gate.
From a gap analysis against NestJS and AdonisJS.
Nest ships
@nestjs/schedule; there is no equivalent here, and a cron/scheduler deployment is one of the most common process kinds a backend needs.It is the cleanest fit for thesis #1 of any missing feature. "One process, one runtime" already says an
api, aconsumerand aworkerare three deployments of the same module under different runtimes — ascheduleris simply the fourth. Everything the kernel asks of a runtime is already answerable for it:RunUnitalready exists; a tick is a natural unit, with the schedule entry's name asUnitMeta.idand a mintedtraceIdper firing (per the second contract a runtime owes — a schedule name is a category, not a unique id, which is exactly the trap that contract documents).Serving.drain. Stop firing new ticks, wait for in-flight ones, honour the kernel's deadline signal. Simpler than@btravstack/temporal's, which already solves the harder version of this.Serving.info. The schedule, so an operator can read back what this process actually runs — the same wayAmqpInfoderivesqueuesfrom the contract rather than from an option that could disagree.Design questions worth settling in the issue rather than in code: whether schedules are declared as a contract (like the other three starters) or as options; whether a missed tick is skipped or caught up; and whether multi-replica coordination is in scope at all, or explicitly left to the application (a leader-election port, or "run one replica").
Acceptance
@btravstack/schedulerstarter providing aSchedulerRuntimeover core'sRuntimePort, withneeds: []like the other three.traceIdper firing.drainstops scheduling and waits for in-flight ticks, released at the kernel's deadline.examples/is part of the gate.