mirror of
https://github.com/xtr-dev/payload-mailing.git
synced 2025-12-10 00:03:23 +00:00
Fix critical error handling and race condition issues
🔴 Critical fixes: - Fix race condition: processImmediately now properly fails if job creation fails - Fix silent job failures: job creation failures now throw errors instead of warnings - Ensure atomic operations: either email + job succeed together, or both fail ⚠️ Improvements: - Simplify error handling in processEmailJob to be more consistent - Add proper validation for missing PayloadCMS jobs configuration - Make error messages more descriptive and actionable
This commit is contained in:
@@ -64,13 +64,7 @@ export const processEmailJob = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Re-throw Error instances to preserve stack trace and error context
|
throw new Error(`Failed to process email ${emailId}: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
if (error instanceof Error) {
|
|
||||||
throw error
|
|
||||||
} else {
|
|
||||||
// Only wrap non-Error values
|
|
||||||
throw new Error(`Failed to process email ${emailId}: ${String(error)}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,36 +145,44 @@ export const sendEmail = async <TEmail extends BaseEmailDocument = BaseEmailDocu
|
|||||||
// Create an individual job for this email
|
// Create an individual job for this email
|
||||||
const queueName = options.queue || mailingConfig.queue || 'default'
|
const queueName = options.queue || mailingConfig.queue || 'default'
|
||||||
|
|
||||||
let jobId: string | undefined
|
if (!payload.jobs) {
|
||||||
|
if (options.processImmediately) {
|
||||||
if (payload.jobs) {
|
throw new Error('PayloadCMS jobs not configured - cannot process email immediately')
|
||||||
try {
|
} else {
|
||||||
const job = await payload.jobs.queue({
|
console.warn('PayloadCMS jobs not configured - emails will not be processed automatically')
|
||||||
queue: queueName,
|
return email as TEmail
|
||||||
task: 'process-email',
|
|
||||||
input: {
|
|
||||||
emailId: String(email.id)
|
|
||||||
},
|
|
||||||
// If scheduled, set the waitUntil date
|
|
||||||
waitUntil: emailData.scheduledAt ? new Date(emailData.scheduledAt) : undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
jobId = String(job.id)
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`Failed to create job for email ${email.id}:`, error)
|
|
||||||
// Don't fail the entire sendEmail operation if job creation fails
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.warn('PayloadCMS jobs not configured - emails will not be processed automatically')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If processImmediately is true and we have a job, process it now
|
let jobId: string
|
||||||
if (options.processImmediately && jobId) {
|
try {
|
||||||
|
const job = await payload.jobs.queue({
|
||||||
|
queue: queueName,
|
||||||
|
task: 'process-email',
|
||||||
|
input: {
|
||||||
|
emailId: String(email.id)
|
||||||
|
},
|
||||||
|
// If scheduled, set the waitUntil date
|
||||||
|
waitUntil: emailData.scheduledAt ? new Date(emailData.scheduledAt) : undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
jobId = String(job.id)
|
||||||
|
} catch (error) {
|
||||||
|
if (options.processImmediately) {
|
||||||
|
// If immediate processing was requested, job creation failure is critical
|
||||||
|
throw new Error(`Failed to create job for immediate processing of email ${email.id}: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
} else {
|
||||||
|
// For regular queued emails, job creation failure is still critical
|
||||||
|
throw new Error(`Failed to create processing job for email ${email.id}: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If processImmediately is true, process the job now
|
||||||
|
if (options.processImmediately) {
|
||||||
try {
|
try {
|
||||||
await processJobById(payload, jobId)
|
await processJobById(payload, jobId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`Failed to process email ${email.id} immediately:`, error)
|
throw new Error(`Failed to process email ${email.id} immediately: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
// Don't fail the entire sendEmail operation if immediate processing fails
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user