Skip to content

Commit 05b9d94

Browse files
authored
fix: delete scheduled publish jobs when deleting documents (#10584)
### What? When a document gets deleted we are not cleaning up jobs that would fail if the document doesn't exist. This change makes an extra call to the DB to delete any incomplete jobs for the document. ### Why? The jobs queue will error and retry needlessly unless these are purged. ### How? Adds a call to delete jobs from the delete operation.
1 parent d4039f2 commit 05b9d94

File tree

5 files changed

+178
-3
lines changed

5 files changed

+178
-3
lines changed

packages/payload/src/collections/operations/delete.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { commitTransaction } from '../../utilities/commitTransaction.js'
2323
import { initTransaction } from '../../utilities/initTransaction.js'
2424
import { killTransaction } from '../../utilities/killTransaction.js'
2525
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions.js'
26+
import { deleteScheduledPublishJobs } from '../../versions/deleteScheduledPublishJobs.js'
2627
import { buildAfterOperation } from './utils.js'
2728

2829
export type Arguments = {
@@ -177,6 +178,18 @@ export const deleteOperation = async <
177178
})
178179
}
179180

181+
// /////////////////////////////////////
182+
// Delete scheduled posts
183+
// /////////////////////////////////////
184+
if (collectionConfig.versions?.drafts && collectionConfig.versions.drafts.schedulePublish) {
185+
await deleteScheduledPublishJobs({
186+
id,
187+
slug: collectionConfig.slug,
188+
payload,
189+
req,
190+
})
191+
}
192+
180193
// /////////////////////////////////////
181194
// Delete document
182195
// /////////////////////////////////////

packages/payload/src/collections/operations/deleteByID.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { commitTransaction } from '../../utilities/commitTransaction.js'
1919
import { initTransaction } from '../../utilities/initTransaction.js'
2020
import { killTransaction } from '../../utilities/killTransaction.js'
2121
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions.js'
22+
import { deleteScheduledPublishJobs } from '../../versions/deleteScheduledPublishJobs.js'
2223
import { buildAfterOperation } from './utils.js'
2324

2425
export type Arguments = {
@@ -155,6 +156,18 @@ export const deleteByIDOperation = async <TSlug extends CollectionSlug, TSelect
155156
})
156157
}
157158

159+
// /////////////////////////////////////
160+
// Delete scheduled posts
161+
// /////////////////////////////////////
162+
if (collectionConfig.versions?.drafts && collectionConfig.versions.drafts.schedulePublish) {
163+
await deleteScheduledPublishJobs({
164+
id,
165+
slug: collectionConfig.slug,
166+
payload,
167+
req,
168+
})
169+
}
170+
158171
// /////////////////////////////////////
159172
// Delete document
160173
// /////////////////////////////////////

packages/payload/src/versions/deleteCollectionVersions.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ export const deleteCollectionVersions = async ({ id, slug, payload, req }: Args)
2121
},
2222
})
2323
} catch (err) {
24-
payload.logger.error(
25-
`There was an error removing versions for the deleted ${slug} document with ID ${id}.`,
26-
)
24+
payload.logger.error({
25+
err,
26+
msg: `There was an error removing versions for the deleted ${slug} document with ID ${id}.`,
27+
})
2728
}
2829
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { PayloadRequest } from '../types/index.js'
2+
3+
import { type Payload } from '../index.js'
4+
5+
type Args = {
6+
id?: number | string
7+
payload: Payload
8+
req?: PayloadRequest
9+
slug: string
10+
}
11+
12+
export const deleteScheduledPublishJobs = async ({
13+
id,
14+
slug,
15+
payload,
16+
req,
17+
}: Args): Promise<void> => {
18+
try {
19+
await payload.db.deleteMany({
20+
collection: 'payload-jobs',
21+
req,
22+
where: {
23+
and: [
24+
// only want to delete jobs have not run yet
25+
{
26+
completedAt: {
27+
exists: false,
28+
},
29+
},
30+
{
31+
processing: {
32+
equals: false,
33+
},
34+
},
35+
{
36+
'input.doc.value': {
37+
equals: id,
38+
},
39+
},
40+
{
41+
'input.doc.relationTo': {
42+
equals: slug,
43+
},
44+
},
45+
// data.type narrows scheduled publish jobs in case of another job having input.doc.value
46+
{
47+
taskSlug: {
48+
equals: 'schedulePublish',
49+
},
50+
},
51+
],
52+
},
53+
})
54+
} catch (err) {
55+
payload.logger.error({
56+
err,
57+
msg: `There was an error deleting scheduled publish jobs from the queue for ${slug} document with ID ${id}.`,
58+
})
59+
}
60+
}

test/versions/int.spec.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,94 @@ describe('Versions', () => {
19441944
expect(retrieved._status).toStrictEqual('draft')
19451945
})
19461946

1947+
it('should delete scheduled jobs after a document is deleted', async () => {
1948+
const draft = await payload.create({
1949+
collection: draftCollectionSlug,
1950+
data: {
1951+
title: 'my doc to publish in the future',
1952+
description: 'hello',
1953+
},
1954+
draft: true,
1955+
})
1956+
1957+
expect(draft._status).toStrictEqual('draft')
1958+
1959+
const currentDate = new Date()
1960+
1961+
await payload.jobs.queue({
1962+
task: 'schedulePublish',
1963+
waitUntil: new Date(currentDate.getTime() + 3000),
1964+
input: {
1965+
type: 'publish',
1966+
doc: {
1967+
relationTo: draftCollectionSlug,
1968+
value: draft.id,
1969+
},
1970+
},
1971+
})
1972+
1973+
await payload.delete({
1974+
collection: draftCollectionSlug,
1975+
where: {
1976+
id: { equals: draft.id },
1977+
},
1978+
})
1979+
1980+
const { docs } = await payload.find({
1981+
collection: 'payload-jobs',
1982+
where: {
1983+
'input.doc.value': {
1984+
equals: draft.id,
1985+
},
1986+
},
1987+
})
1988+
1989+
expect(docs[0]).toBeUndefined()
1990+
})
1991+
1992+
it('should delete scheduled jobs after a document is deleted by ID', async () => {
1993+
const draft = await payload.create({
1994+
collection: draftCollectionSlug,
1995+
data: {
1996+
title: 'my doc to publish in the future',
1997+
description: 'hello',
1998+
},
1999+
draft: true,
2000+
})
2001+
2002+
expect(draft._status).toStrictEqual('draft')
2003+
2004+
const currentDate = new Date()
2005+
2006+
await payload.jobs.queue({
2007+
task: 'schedulePublish',
2008+
waitUntil: new Date(currentDate.getTime() + 3000),
2009+
input: {
2010+
type: 'publish',
2011+
doc: {
2012+
relationTo: draftCollectionSlug,
2013+
value: draft.id,
2014+
},
2015+
},
2016+
})
2017+
2018+
await payload.delete({
2019+
collection: draftCollectionSlug,
2020+
id: draft.id,
2021+
})
2022+
2023+
const { docs } = await payload.find({
2024+
collection: 'payload-jobs',
2025+
where: {
2026+
'input.doc.value': {
2027+
equals: draft.id,
2028+
},
2029+
},
2030+
})
2031+
2032+
expect(docs[0]).toBeUndefined()
2033+
})
2034+
19472035
it('should allow global scheduled publish', async () => {
19482036
const draft = await payload.updateGlobal({
19492037
slug: draftGlobalSlug,

0 commit comments

Comments
 (0)