Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add payload.jobs.runByID #9875

Merged
merged 4 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/jobs-queue/queues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,23 @@ After the project is deployed to Vercel, the Vercel Cron job will automatically

If you want to process jobs programmatically from your server-side code, you can use the Local API:

**Run all jobs:**

```ts
const results = await payload.jobs.run()

// You can customize the queue name and limit by passing them as arguments:
await payload.jobs.run({ queue: 'nightly', limit: 100 })
```

**Run a single job:**

```ts
const results = await payload.jobs.runByID({
id: myJobID
})
```

#### Bin script

Finally, you can process jobs via the bin script that comes with Payload out of the box.
Expand Down
14 changes: 14 additions & 0 deletions packages/payload/src/queues/localAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,18 @@ export const getJobsLocalAPI = (payload: Payload) => ({
})
return result
},

runByID: async (args: {
id: number | string
overrideAccess?: boolean
req?: PayloadRequest
}): Promise<ReturnType<typeof runJobs>> => {
const newReq: PayloadRequest = args?.req ?? (await createLocalReq({}, payload))
const result = await runJobs({
id: args.id,
overrideAccess: args?.overrideAccess !== false,
req: newReq,
})
return result
},
})
47 changes: 35 additions & 12 deletions packages/payload/src/queues/operations/runJobs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import { runJob } from './runJob/index.js'
import { runJSONJob } from './runJSONJob/index.js'

export type RunJobsArgs = {
/**
* ID of the job to run
*/
id?: number | string
limit?: number
overrideAccess?: boolean
queue?: string
Expand All @@ -36,6 +40,7 @@ export type RunJobsResult = {
}

export const runJobs = async ({
id,
limit = 10,
overrideAccess,
queue,
Expand Down Expand Up @@ -91,18 +96,36 @@ export const runJobs = async ({

// Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of
// the same job being picked up by another worker
const jobsQuery = (await req.payload.update({
collection: 'payload-jobs',
data: {
processing: true,
seenByWorker: true,
},
depth: req.payload.config.jobs.depth,
disableTransaction: true,
limit,
showHiddenFields: true,
where,
})) as unknown as PaginatedDocs<BaseJob>
const jobsQuery: {
docs: BaseJob[]
} = id
? {
docs: [
(await req.payload.update({
id,
collection: 'payload-jobs',
data: {
processing: true,
seenByWorker: true,
},
depth: req.payload.config.jobs.depth,
disableTransaction: true,
showHiddenFields: true,
})) as BaseJob,
],
}
: ((await req.payload.update({
collection: 'payload-jobs',
data: {
processing: true,
seenByWorker: true,
},
depth: req.payload.config.jobs.depth,
disableTransaction: true,
limit,
showHiddenFields: true,
where,
})) as unknown as PaginatedDocs<BaseJob>)

/**
* Just for logging purposes, we want to know how many jobs are new and how many are existing (= already been tried).
Expand Down
40 changes: 40 additions & 0 deletions test/queues/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}
})

beforeEach(async () => {

Check failure on line 32 in test/queues/int.spec.ts

View workflow job for this annotation

GitHub Actions / int-mongodb

Queues › ensure default jobs run limit of 10 works

thrown: "Exceeded timeout of 90000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at beforeEach (queues/int.spec.ts:32:3) at Object.describe (queues/int.spec.ts:20:1)

Check failure on line 32 in test/queues/int.spec.ts

View workflow job for this annotation

GitHub Actions / int-mongodb

Queues › ensure jobs run limit can be customized

thrown: "Exceeded timeout of 90000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at beforeEach (queues/int.spec.ts:32:3) at Object.describe (queues/int.spec.ts:20:1)

Check failure on line 32 in test/queues/int.spec.ts

View workflow job for this annotation

GitHub Actions / int-mongodb

Queues › can queue different kinds of single tasks multiple times

thrown: "Exceeded timeout of 90000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at beforeEach (queues/int.spec.ts:32:3) at Object.describe (queues/int.spec.ts:20:1)

Check failure on line 32 in test/queues/int.spec.ts

View workflow job for this annotation

GitHub Actions / int-mongodb

Queues › can queue external tasks

thrown: "Exceeded timeout of 90000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at beforeEach (queues/int.spec.ts:32:3) at Object.describe (queues/int.spec.ts:20:1)

Check failure on line 32 in test/queues/int.spec.ts

View workflow job for this annotation

GitHub Actions / int-mongodb

Queues › can queue external workflow that is running external task

thrown: "Exceeded timeout of 90000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at beforeEach (queues/int.spec.ts:32:3) at Object.describe (queues/int.spec.ts:20:1)

Check failure on line 32 in test/queues/int.spec.ts

View workflow job for this annotation

GitHub Actions / int-mongodb

Queues › ensure payload.jobs.runByID works and only runs the specified job

thrown: "Exceeded timeout of 90000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at beforeEach (queues/int.spec.ts:32:3) at Object.describe (queues/int.spec.ts:20:1)
await clearAndSeedEverything(payload)
const data = await restClient
.POST('/users/login', {
Expand Down Expand Up @@ -925,4 +925,44 @@
expect(allSimples.totalDocs).toBe(1)
expect(allSimples.docs[0].title).toBe('externalWorkflow')
})

it('ensure payload.jobs.runByID works and only runs the specified job', async () => {
payload.config.jobs.deleteJobOnComplete = false

let lastJobID: string = null
for (let i = 0; i < 3; i++) {
const job = await payload.jobs.queue({
task: 'CreateSimple',
input: {
message: 'from single task',
},
})
lastJobID = job.id
}

await payload.jobs.runByID({
id: lastJobID,
})

const allSimples = await payload.find({
collection: 'simple',
limit: 100,
})

expect(allSimples.totalDocs).toBe(1)
expect(allSimples.docs[0].title).toBe('from single task')

const allCompletedJobs = await payload.find({
collection: 'payload-jobs',
limit: 100,
where: {
completedAt: {
exists: true,
},
},
})

expect(allCompletedJobs.totalDocs).toBe(1)
expect(allCompletedJobs.docs[0].id).toBe(lastJobID)
})
})
Loading