fix: ensure errors returned from tasks are properly logged (#11443)
Fixes https://github.com/payloadcms/payload/issues/9767 We allow failing a job queue task by returning `{ state: 'failed' }` from the task, instead of throwing an error. However, previously, this threw an error when trying to update the task in the database. Additionally, it was not possible to customize the error message. This PR fixes that by letting you return `errorMessage` alongside `{ state: 'failed' }`, and by ensuring the error is transformed into proper json before saving it to the `error` column.
This commit is contained in:
@@ -323,6 +323,44 @@ export default buildConfigWithDefaults({
|
||||
],
|
||||
handler: path.resolve(dirname, 'runners/externalTask.ts') + '#externalTaskHandler',
|
||||
} as TaskConfig<'ExternalTask'>,
|
||||
{
|
||||
retries: 0,
|
||||
slug: 'ThrowError',
|
||||
inputSchema: [],
|
||||
outputSchema: [],
|
||||
handler: () => {
|
||||
throw new Error('failed')
|
||||
},
|
||||
} as TaskConfig<'ThrowError'>,
|
||||
{
|
||||
retries: 0,
|
||||
slug: 'ReturnError',
|
||||
inputSchema: [],
|
||||
outputSchema: [],
|
||||
handler: () => {
|
||||
return {
|
||||
state: 'failed',
|
||||
}
|
||||
},
|
||||
} as TaskConfig<'ReturnError'>,
|
||||
{
|
||||
retries: 0,
|
||||
slug: 'ReturnCustomError',
|
||||
inputSchema: [
|
||||
{
|
||||
name: 'errorMessage',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputSchema: [],
|
||||
handler: ({ input }) => {
|
||||
return {
|
||||
state: 'failed',
|
||||
errorMessage: input.errorMessage,
|
||||
}
|
||||
},
|
||||
} as TaskConfig<'ReturnCustomError'>,
|
||||
],
|
||||
workflows: [
|
||||
updatePostWorkflow,
|
||||
|
||||
@@ -1128,4 +1128,69 @@ describe('Queues', () => {
|
||||
// @ts-expect-error
|
||||
expect(jobAfterRun.input.amountTask1Retried).toBe(0)
|
||||
})
|
||||
|
||||
it('can tasks throw error', async () => {
|
||||
payload.config.jobs.deleteJobOnComplete = false
|
||||
|
||||
const job = await payload.jobs.queue({
|
||||
task: 'ThrowError',
|
||||
input: {},
|
||||
})
|
||||
|
||||
await payload.jobs.run()
|
||||
|
||||
const jobAfterRun = await payload.findByID({
|
||||
collection: 'payload-jobs',
|
||||
id: job.id,
|
||||
})
|
||||
|
||||
expect(jobAfterRun.hasError).toBe(true)
|
||||
expect(jobAfterRun.log?.length).toBe(1)
|
||||
expect(jobAfterRun.log[0].error.message).toBe('failed')
|
||||
expect(jobAfterRun.log[0].state).toBe('failed')
|
||||
})
|
||||
|
||||
it('can tasks return error', async () => {
|
||||
payload.config.jobs.deleteJobOnComplete = false
|
||||
|
||||
const job = await payload.jobs.queue({
|
||||
task: 'ReturnError',
|
||||
input: {},
|
||||
})
|
||||
|
||||
await payload.jobs.run()
|
||||
|
||||
const jobAfterRun = await payload.findByID({
|
||||
collection: 'payload-jobs',
|
||||
id: job.id,
|
||||
})
|
||||
|
||||
expect(jobAfterRun.hasError).toBe(true)
|
||||
expect(jobAfterRun.log?.length).toBe(1)
|
||||
expect(jobAfterRun.log[0].error.message).toBe('failed')
|
||||
expect(jobAfterRun.log[0].state).toBe('failed')
|
||||
})
|
||||
|
||||
it('can tasks return error with custom error message', async () => {
|
||||
payload.config.jobs.deleteJobOnComplete = false
|
||||
|
||||
const job = await payload.jobs.queue({
|
||||
task: 'ReturnCustomError',
|
||||
input: {
|
||||
errorMessage: 'custom error message',
|
||||
},
|
||||
})
|
||||
|
||||
await payload.jobs.run()
|
||||
|
||||
const jobAfterRun = await payload.findByID({
|
||||
collection: 'payload-jobs',
|
||||
id: job.id,
|
||||
})
|
||||
|
||||
expect(jobAfterRun.hasError).toBe(true)
|
||||
expect(jobAfterRun.log?.length).toBe(1)
|
||||
expect(jobAfterRun.log[0].error.message).toBe('custom error message')
|
||||
expect(jobAfterRun.log[0].state).toBe('failed')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user