Running tick
Rungs has no background thread. Deadlines, reminders, escalations, timeouts and the reminders of
blocked steps are applied when you call rungs.tick(), at the time your clock returns. Run it
on a schedule:
// One loop in a worker process: apply what is due, then deliver events. Several workers may run// at once; with the PostgreSQL store they claim different requests (EC-27).export function startWorker(rungs: Rungs, everyMs = 60_000): () => void { let running = false; const run = async () => { if (running) return; // never overlap with a slow previous run running = true; try { const { failed } = await rungs.tick({ limit: 500 }); for (const { requestId, error } of failed) console.error("tick failed", requestId, error); await rungs.dispatchPending({ limit: 500 }); } catch (error) { console.error("worker run failed", error); // the next run tries again } finally { running = false; } }; const timer = setInterval(run, everyMs); void run(); return () => clearInterval(timer);}Runs in CI:examples/docs-snippets/src/guides/tick.ts
- How often: every minute is plenty for deadlines measured in hours or days.
- Several workers: safe. Each due action is applied once, and the PostgreSQL store hands different requests to different workers (EC-27).
- Missed runs: a late tick catches up with one reminder, not one per missed interval.
- Failures: one failing request does not stop the others; it is reported in
failedand tried again next time.
On serverless platforms, call the same two functions from a scheduled function or cron route
instead of setInterval.