Defining Jobs
Use job() to define a job and createJobRouter() to group them into a router. The input field accepts any Standard Schema-compatible library — Zod, Valibot, ArkType, and others.
import { createJobRouter, job } from "@queuebase/nextjs"; // or @queuebase/nodeimport { z } from "zod"; // or valibot, arktype, etc.
export const jobs = createJobRouter({ myJob: job({ input: z.object({ /* your schema */ }), handler: async (ctx) => { /* returns output */ }, defaults: { /* optional EnqueueOptions */ }, }),});Handler context
Section titled “Handler context”The handler receives a JobContext object:
| Field | Type | Description |
|---|---|---|
input | Inferred from schema | Validated input data |
jobId | string | Unique job ID |
attempt | number | Current attempt (1-indexed) |
maxAttempts | number | Maximum attempts allowed |
fail | (reason: string) => never | Explicitly fail the job |
handler: async ({ input, jobId, attempt, maxAttempts }) => { console.log(`Job ${jobId}, attempt ${attempt}/${maxAttempts}`); // use input (fully typed from your schema) return { success: true };}Explicitly failing a job
Section titled “Explicitly failing a job”Call ctx.fail() to immediately mark a job as failed with a reason. This throws a JobFailureError internally, so any code after it won’t run.
handler: async ({ input, fail }) => { const user = await findUser(input.userId); if (!user) { fail("User not found"); }
// this only runs if user exists await sendEmail(user.email); return { sent: true };}This is useful when a job should fail for a business logic reason rather than an unexpected exception. The failure reason is recorded on the job and visible in the dashboard.
Defaults
Section titled “Defaults”You can set default enqueue options per job via the defaults field. These are merged with (and overridden by) options passed to .enqueue().
sendEmail: job({ input: z.object({ to: z.string().email() }), handler: async ({ input }) => { // ... return { sent: true }; }, defaults: { retries: 3, backoff: "exponential", backoffDelay: 2000, },}),See Enqueueing Jobs for the full list of options.
Schedules
Section titled “Schedules”Jobs with an empty input schema can define a schedule to run automatically on a cron schedule:
cleanupExpired: job({ input: z.object({}), handler: async () => { // runs every hour return { cleaned: true }; }, schedule: "every hour",}),Schedules accept plain English strings ("every day at 9am"), raw cron expressions ("0 9 * * *"), or a config object for full control over timezone and overlap behavior. See Scheduled Jobs for details.