mirror of
https://github.com/xtr-dev/payload-mailing.git
synced 2025-12-10 00:03:23 +00:00
Add has-many relationship from emails to processing jobs
✨ New Feature: - Add 'jobs' relationship field to emails collection - Shows all PayloadCMS jobs associated with each email - Read-only field with smart filtering by emailId - Visible in admin interface for better email tracking 🔍 Benefits: - Track job status and history for each email - Debug processing issues more easily - Monitor job queue performance per email - Complete email processing visibility
This commit is contained in:
@@ -4,7 +4,7 @@ const Emails: CollectionConfig = {
|
|||||||
slug: 'emails',
|
slug: 'emails',
|
||||||
admin: {
|
admin: {
|
||||||
useAsTitle: 'subject',
|
useAsTitle: 'subject',
|
||||||
defaultColumns: ['subject', 'to', 'status', 'scheduledAt', 'sentAt'],
|
defaultColumns: ['subject', 'to', 'status', 'jobs', 'scheduledAt', 'sentAt'],
|
||||||
group: 'Mailing',
|
group: 'Mailing',
|
||||||
description: 'Email delivery and status tracking',
|
description: 'Email delivery and status tracking',
|
||||||
},
|
},
|
||||||
@@ -164,6 +164,24 @@ const Emails: CollectionConfig = {
|
|||||||
description: 'Email priority (1=highest, 10=lowest)',
|
description: 'Email priority (1=highest, 10=lowest)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'jobs',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'payload-jobs',
|
||||||
|
hasMany: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Processing jobs associated with this email',
|
||||||
|
allowCreate: false,
|
||||||
|
readOnly: true,
|
||||||
|
},
|
||||||
|
filterOptions: ({ id }) => {
|
||||||
|
return {
|
||||||
|
'input.emailId': {
|
||||||
|
equals: id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
// indexes: [
|
// indexes: [
|
||||||
|
|||||||
@@ -168,13 +168,19 @@ export const sendEmail = async <TEmail extends BaseEmailDocument = BaseEmailDocu
|
|||||||
|
|
||||||
jobId = String(job.id)
|
jobId = String(job.id)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (options.processImmediately) {
|
// Clean up the orphaned email since job creation failed
|
||||||
// If immediate processing was requested, job creation failure is critical
|
try {
|
||||||
throw new Error(`Failed to create job for immediate processing of email ${email.id}: ${error instanceof Error ? error.message : String(error)}`)
|
await payload.delete({
|
||||||
} else {
|
collection: collectionSlug,
|
||||||
// For regular queued emails, job creation failure is still critical
|
id: email.id
|
||||||
throw new Error(`Failed to create processing job for email ${email.id}: ${error instanceof Error ? error.message : String(error)}`)
|
})
|
||||||
|
} catch (deleteError) {
|
||||||
|
console.error(`Failed to clean up orphaned email ${email.id} after job creation failure:`, deleteError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Throw the original job creation error
|
||||||
|
const errorMsg = `Failed to create processing job for email ${email.id}: ${String(error)}`
|
||||||
|
throw new Error(errorMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If processImmediately is true, process the job now
|
// If processImmediately is true, process the job now
|
||||||
@@ -182,7 +188,9 @@ export const sendEmail = async <TEmail extends BaseEmailDocument = BaseEmailDocu
|
|||||||
try {
|
try {
|
||||||
await processJobById(payload, jobId)
|
await processJobById(payload, jobId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to process email ${email.id} immediately: ${error instanceof Error ? error.message : String(error)}`)
|
// For immediate processing failures, we could consider cleanup, but the job exists and could be retried later
|
||||||
|
// So we'll leave the email and job in place for potential retry
|
||||||
|
throw new Error(`Failed to process email ${email.id} immediately: ${String(error)}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export async function processJobById(payload: Payload, jobId: string): Promise<v
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to process job ${jobId}: ${error instanceof Error ? error.message : String(error)}`)
|
throw new Error(`Failed to process job ${jobId}: ${String(error)}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user