Skip to content

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/cron

Declare

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"

tenantBehaviour
"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).
OmittedTreated 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

MIT licensed.