Skip to content

Commit dff3d1b

Browse files
authored
docs: updates Jobs queue docs (#14552)
1 parent ad74386 commit dff3d1b

File tree

7 files changed

+1124
-25
lines changed

7 files changed

+1124
-25
lines changed

docs/jobs-queue/jobs.mdx

Lines changed: 187 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Jobs
33
label: Jobs
4-
order: 40
4+
order: 50
55
desc: A Job is a set of work that is offloaded from your APIs and will be processed at a later date.
66
keywords: jobs queue, application framework, typescript, node, react, nextjs
77
---
@@ -47,6 +47,186 @@ const createdJob = await payload.jobs.queue({
4747
})
4848
```
4949

50+
### Where to Queue Jobs
51+
52+
Jobs can be queued from anywhere in your application. Here are the most common scenarios:
53+
54+
#### From Collection Hooks
55+
56+
The most common place - queue jobs in response to document changes:
57+
58+
```ts
59+
{
60+
slug: 'posts',
61+
hooks: {
62+
afterChange: [
63+
async ({ req, doc, operation }) => {
64+
// Only send notification for published posts
65+
if (operation === 'update' && doc.status === 'published') {
66+
await req.payload.jobs.queue({
67+
task: 'notifySubscribers',
68+
input: {
69+
postId: doc.id,
70+
},
71+
})
72+
}
73+
},
74+
],
75+
},
76+
}
77+
```
78+
79+
#### From Field Hooks
80+
81+
Queue jobs based on specific field changes:
82+
83+
```ts
84+
{
85+
name: 'featuredImage',
86+
type: 'upload',
87+
relationTo: 'media',
88+
hooks: {
89+
afterChange: [
90+
async ({ req, value, previousValue }) => {
91+
// Generate image variants when image changes
92+
if (value !== previousValue) {
93+
await req.payload.jobs.queue({
94+
task: 'generateImageVariants',
95+
input: {
96+
imageId: value,
97+
},
98+
})
99+
}
100+
},
101+
],
102+
},
103+
}
104+
```
105+
106+
#### From Custom Endpoints
107+
108+
Queue jobs from your API routes:
109+
110+
```ts
111+
export const POST = async (req: PayloadRequest) => {
112+
const job = await req.payload.jobs.queue({
113+
workflow: 'generateMonthlyReport',
114+
input: {
115+
month: new Date().getMonth(),
116+
year: new Date().getFullYear(),
117+
},
118+
})
119+
120+
return Response.json({
121+
message: 'Report generation queued',
122+
jobId: job.id,
123+
})
124+
}
125+
```
126+
127+
#### From Server Actions
128+
129+
Queue jobs from Next.js server actions:
130+
131+
```ts
132+
'use server'
133+
134+
import { getPayload } from 'payload'
135+
import config from '@payload-config'
136+
137+
export async function scheduleEmail(userId: string) {
138+
const payload = await getPayload({ config })
139+
140+
await payload.jobs.queue({
141+
task: 'sendEmail',
142+
input: { userId },
143+
})
144+
}
145+
```
146+
147+
### Job Options
148+
149+
When queuing a job, you can pass additional options:
150+
151+
```ts
152+
await payload.jobs.queue({
153+
task: 'sendEmail',
154+
input: { userId: '123' },
155+
156+
// Schedule the job to run in the future
157+
waitUntil: new Date('2024-12-25T00:00:00Z'),
158+
159+
// Assign to a specific queue
160+
queue: 'high-priority',
161+
162+
// Add custom metadata for tracking
163+
log: [
164+
{
165+
message: 'Email queued by admin',
166+
createdAt: new Date().toISOString(),
167+
},
168+
],
169+
})
170+
```
171+
172+
#### Common options
173+
174+
- `waitUntil` - Schedule the job to run at a specific date/time in the future
175+
- `queue` - Assign the job to a specific queue (defaults to `'default'`)
176+
- `log` - Add custom log entries for debugging or tracking
177+
- `req` - Pass the request context for access control
178+
179+
#### Check Job Status
180+
181+
After queuing a job, you can check its status:
182+
183+
```ts
184+
const job = await payload.jobs.queue({
185+
task: 'processPayment',
186+
input: { orderId: '123' },
187+
})
188+
189+
// Later, check the job status
190+
const updatedJob = await payload.findByID({
191+
collection: 'payload-jobs',
192+
id: job.id,
193+
})
194+
195+
console.log(updatedJob.completedAt) // When it finished
196+
console.log(updatedJob.hasError) // If it failed
197+
console.log(updatedJob.taskStatus) // Details of each task
198+
```
199+
200+
#### Job Status Fields
201+
202+
Each job document contains:
203+
204+
```ts
205+
{
206+
id: 'job_123',
207+
taskSlug: 'sendEmail', // Or workflowSlug for workflows
208+
input: { userId: '123' }, // The input you provided
209+
completedAt: '2024-01-15...', // When job completed (null if pending)
210+
hasError: false, // True if job failed
211+
totalTried: 1, // Number of attempts
212+
processing: false, // True if currently running
213+
taskStatus: { // Status of each task (for workflows)
214+
sendEmail: {
215+
'1': {
216+
complete: true,
217+
output: { emailSent: true }
218+
}
219+
}
220+
},
221+
log: [ // Execution log
222+
{
223+
message: 'Job started',
224+
createdAt: '...'
225+
}
226+
]
227+
}
228+
```
229+
50230
#### Access Control
51231

52232
By default, Payload's job operations bypass access control when used from the Local API. You can enable access control by passing `overrideAccess: false` to any job operation.
@@ -92,12 +272,16 @@ await payload.jobs.queue({
92272
})
93273
```
94274

275+
<Banner type="warning">
276+
It is not recommended to modify the `payload-jobs` collection's access control
277+
directly, as that pattern may be deprecated in future versions. Instead—use
278+
the `access` property in your Jobs Config to control job operations.
279+
</Banner>
280+
95281
#### Cancelling Jobs
96282

97283
Payload allows you to cancel jobs that are either queued or currently running. When cancelling a running job, the current task will finish executing, but no subsequent tasks will run. This happens because the job checks its cancellation status between tasks.
98284

99-
##### Cancel a Single Job
100-
101285
To cancel a specific job, use the `payload.jobs.cancelByID` method with the job's ID:
102286

103287
```ts
@@ -106,8 +290,6 @@ await payload.jobs.cancelByID({
106290
})
107291
```
108292

109-
##### Cancel Multiple Jobs
110-
111293
To cancel multiple jobs at once, use the `payload.jobs.cancel` method with a `Where` query:
112294

113295
```ts

docs/jobs-queue/overview.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Payload's Jobs Queue gives you a simple, yet powerful way to offload large or fu
1010

1111
### Example use cases
1212

13-
**Non-blocking workloads**
13+
#### Non-blocking workloads
1414

1515
You might need to perform some complex, slow-running logic in a Payload [Hook](/docs/hooks/overview) but you don't want that hook to "block" or slow down the response returned from the Payload API. Instead of running this logic directly in a hook, which would block your API response from returning until the expensive work is completed, you can queue a new Job and let it run at a later date.
1616

@@ -20,7 +20,7 @@ Examples:
2020
- Send data to a third-party API on document change
2121
- Trigger emails based on customer actions
2222

23-
**Scheduled actions**
23+
#### Scheduled actions
2424

2525
If you need to schedule an action to be run or processed at a certain date in the future, you can queue a job with the `waitUntil` property set. This will make it so the job is not "picked up" until that `waitUntil` date has passed.
2626

@@ -40,7 +40,7 @@ Examples:
4040
- Periodically trigger a rebuild of your frontend at night
4141
- Sync resources to or from a third-party API during non-peak times
4242

43-
**Offloading complex operations**
43+
#### Offloading complex operations
4444

4545
You may run into the need to perform computationally expensive functions which might slow down your main Payload API server(s). The Jobs Queue allows you to offload these tasks to a separate compute resource rather than slowing down the server(s) that run your Payload APIs. With Payload Task definitions, you can even keep large dependencies out of your main Next.js bundle by dynamically importing them only when they are used. This keeps your Next.js + Payload compilation fast and ensures large dependencies do not get bundled into your Payload production build.
4646

0 commit comments

Comments
 (0)