graphile-worker-tasks
v2.2.0
Published
Organize and collect graphile-worker tasks
Readme
graphile-worker-tasks
A utility for organizing and collecting graphile-worker tasks.
This library is particularly useful when working with graphile-worker in environments where the built-in file-based auto-discovery mechanism is either not possible or not desirable, such as when using bundlers or other specialized setups.
Install
pnpm add graphile-worker-tasksUse
Define tasks:
import { defineTask } from "graphile-worker-tasks"
export default defineTask("sendEmail", async (email: string) => {
console.log(`Sending email: ${email}`)
})You can organize tasks across as many modules as needed.
Once defined, collect and run your tasks:
import { run } from "graphile-worker"
import { createTaskList, mergeTasks } from "graphile-worker-tasks"
import sendEmailTask from "../tasks/sendEmail"
const tasks = mergeTasks([
sendEmailTask,
// ...
])
await run({
connectionString: "...",
taskList: createTaskList(tasks),
parsedCronItems: [],
})Extend GraphileWorker.Tasks to ensure the graphile-worker tooling picks up the types:
declare global {
namespace GraphileWorker {
interface Tasks extends GraphileWorkerTasks<typeof tasks> {}
}
}There is no magic in this module — it just stores the task identifiers and handles the typing quirks.
You can omit the helpers and use the task handlers directly, but make sure to use correct task identifiers:
import { run } from "graphile-worker"
// Import the module under a name that matches the task identifier.
import sendEmail from "../tasks/sendEmail"
await run({
connectionString: "...",
taskList: {
sendEmail, // The key here must match the task identifier.
// ...
},
parsedCronItems: [],
})Binding addJob to tasks
If you want each defined task to also know how to enqueue itself, bind your app's addJob implementation once and use the returned defineTask.
For example, to enqueue jobs within the active Orchid ORM transaction, use addJob from graphile-worker-orchid.
import { createDefineTask } from "graphile-worker-tasks"
import { addJob } from "../my-add-job"
const defineTask = createDefineTask({ addJob })
export const sendEmail = defineTask("sendEmail", async (email: string) => {
console.log(`Sending email: ${email}`)
})
// Collect and run tasks as usual, and also enqueue them directly:
await sendEmail.addJob("[email protected]")If only using the bound addJob, you can omit augmenting namespace GraphileWorker.
Running tasks directly
Tasks can be run directly, which is useful in tests:
await sendEmail.run("[email protected]")By default, run provides a minimal JobHelpers object. The default manual helpers use graphile-worker's console logger and include a synthetic helpers.job for the manual run. Helpers that require a real worker or database context, such as query, withPgClient, addJob, and getQueueName, throw a clear error.
If your task uses those helpers, pass them as the second argument. A partial object is shallow-merged onto the default helpers:
await sendEmail.run("[email protected]", { query: myTestQuery })For helpers that depend on the payload, pass a factory instead. It receives the default helpers and returns the full helpers object:
await sendEmail.run("[email protected]", ({ defaultHelpers, payload }) => ({
...defaultHelpers,
query: queryForTenant(payload),
}))When using a bound defineTask, you can configure helpers once for every task's run. Per-call helpers still override them:
const defineTask = createDefineTask({
addJob,
helpers: { query: myTestQuery },
})