Cron jobs
defineCron declares a scheduled action. The cron plugin owns the timer and dispatches the action on the schedule.
Install
bash
pnpm add @nwire/cronDeclare
ts
import { defineCron } from "@nwire/forge"
export const nightlyDigest = defineCron({
name: "submissions.nightly-digest",
cron: "0 2 * * *", // 02:00 every day
tenant: "all", // run once per tenant
handler: async (_, ctx) => {
const stuck = await ctx.query(StuckSubmissions, {})
if (stuck.length) ctx.emit(DigestWasComputed({ count: stuck.length }))
},
})Plug it in
ts
import { cronPlugin } from "@nwire/cron"
const app = await createApp({
modules: [submissions],
plugins: [cronPlugin()],
})How the schedule fires
The plugin holds an in-memory schedule and dispatches at the right moment. In split deployments, only the worker process loads cronPlugin so the schedule fires once across the cluster.
tenant: "all" vs "none"
tenant | Behaviour |
|---|---|
"all" | The runtime loads every known tenant and dispatches one action per tenant. |
"none" | One dispatch with no tenant set. Useful for cluster-wide jobs (cache warm, metrics flush). |
| Omitted | Treated as "none". |
Testing
ts
import { harness } from "@nwire/test-kit"
const app = harness({ app })
await app.cron.fire("submissions.nightly-digest") // skip the wall clock
expect(app.events).toEmit("submissions.digest-was-computed")See also
- defineWorkflow — for multi-step processes with timers and correlation
- Multi-transport recipe — running cron alongside HTTP and queue