Improve job scheduling hooks to populate relationship immediately

 Enhanced Job Relationship Management:
- Use beforeChange to populate existing jobs in relationship field
- Use afterChange to create new jobs and add them to relationship
- Jobs now appear immediately in the relationship field
- Better handling of updates vs new document creation

🔄 Hook Flow:
1. beforeChange: Find existing jobs for updates and populate relationship
2. afterChange: Create missing jobs and update relationship field
3. Result: Jobs relationship is always populated correctly

📈 Benefits:
- Immediate job visibility in admin interface
- No reliance on dynamic filtering alone
- Proper relationship data in database
- Handles both new emails and status changes
- Prevents duplicate job creation
This commit is contained in:
2025-09-14 21:03:01 +02:00
parent 9a996a33e5
commit 2d270ca527

View File

@@ -184,15 +184,63 @@ const Emails: CollectionConfig = {
},
],
hooks: {
beforeChange: [
async ({ data, originalDoc, req, operation }) => {
// Only process if this is a pending email and we have jobs configured
if (data.status !== 'pending' || !req.payload.jobs) {
return data
}
// For updates, check if status changed to pending or if this was already pending
if (operation === 'update') {
// If it was already pending and still pending, skip (unless jobs field is empty)
if (originalDoc?.status === 'pending' && data.jobs && data.jobs.length > 0) {
return data
}
// For updates where we need to check existing jobs, we need the document ID
if (originalDoc?.id) {
try {
// Check if a processing job already exists for this email
const existingJobs = await req.payload.find({
collection: 'payload-jobs',
where: {
'input.emailId': {
equals: String(originalDoc.id),
},
task: {
equals: 'process-email',
},
},
limit: 10,
})
if (existingJobs.totalDocs > 0) {
// Add existing jobs to the relationship
const existingJobIds = existingJobs.docs.map(job => job.id)
data.jobs = [...(data.jobs || []), ...existingJobIds.filter(id => !data.jobs?.includes(id))]
return data
}
} catch (error) {
console.error(`Failed to check existing jobs for email ${originalDoc.id}:`, error)
}
}
}
// For new emails or updates that need a new job, we'll create it after the document exists
// We'll handle this in afterChange for new documents since we need the ID
return data
}
],
afterChange: [
async ({ doc, previousDoc, req, operation }) => {
// Only process if this is a pending email and we have jobs configured
// Only process if this is a pending email, we have jobs configured, and no job exists yet
if (doc.status !== 'pending' || !req.payload.jobs) {
return
}
// Skip if this is an update and status didn't change to pending
if (operation === 'update' && previousDoc?.status === 'pending') {
// Skip if this is an update and status didn't change to pending, and jobs already exist
if (operation === 'update' && previousDoc?.status === 'pending' && doc.jobs && doc.jobs.length > 0) {
return
}
@@ -211,12 +259,12 @@ const Emails: CollectionConfig = {
limit: 1,
})
// If no job exists, create one
// If no job exists, create one and add it to the relationship
if (existingJobs.totalDocs === 0) {
const mailingContext = (req.payload as any).mailing
const queueName = mailingContext?.config?.queue || 'default'
await req.payload.jobs.queue({
const job = await req.payload.jobs.queue({
queue: queueName,
task: 'process-email',
input: {
@@ -226,7 +274,16 @@ const Emails: CollectionConfig = {
waitUntil: doc.scheduledAt ? new Date(doc.scheduledAt) : undefined
})
console.log(`Auto-scheduled processing job for email ${doc.id}`)
// Update the email document to include the job in the relationship
await req.payload.update({
collection: 'emails',
id: doc.id,
data: {
jobs: [...(doc.jobs || []), job.id]
}
})
console.log(`Auto-scheduled processing job ${job.id} for email ${doc.id}`)
}
} catch (error) {
console.error(`Failed to auto-schedule job for email ${doc.id}:`, error)