Simplify job system architecture

- Replace createMailingJobs() function with static mailingJobs array
- Remove complex initialization dependencies and function wrappers
- Jobs now get MailingService from payload context instead of factory injection
- Fix PayloadCMS task handler return types to use proper {output: {}} format
- Eliminate potential initialization race conditions
- Cleaner, more straightforward job registration process

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-13 20:12:14 +02:00
parent 6db27093d1
commit 08b4d49019
4 changed files with 42 additions and 46 deletions

View File

@@ -12,7 +12,7 @@ export { default as EmailTemplates, createEmailTemplatesCollection } from './col
export { default as Emails } from './collections/Emails.js' export { default as Emails } from './collections/Emails.js'
// Jobs (includes the send email task) // Jobs (includes the send email task)
export { createMailingJobs, sendEmailJob } from './jobs/index.js' export { mailingJobs, sendEmailJob } from './jobs/index.js'
export type { SendEmailTaskInput } from './jobs/sendEmailTask.js' export type { SendEmailTaskInput } from './jobs/sendEmailTask.js'
// Utility functions for developers // Utility functions for developers

View File

@@ -2,21 +2,34 @@ import { processEmailsJob, ProcessEmailsJobData } from './processEmailsJob.js'
import { sendEmailJob } from './sendEmailTask.js' import { sendEmailJob } from './sendEmailTask.js'
import { MailingService } from '../services/MailingService.js' import { MailingService } from '../services/MailingService.js'
export const createMailingJobs = (mailingService: MailingService): any[] => { export const mailingJobs = [
return [ {
{ slug: 'processEmails',
slug: 'processEmails', handler: async ({ job, req }: { job: any; req: any }) => {
handler: async ({ job, req }: { job: any; req: any }) => { // Get mailing context from payload
return processEmailsJob( const payload = (req as any).payload
job as { data: ProcessEmailsJobData }, const mailingContext = payload.mailing
{ req, mailingService } if (!mailingContext) {
) throw new Error('Mailing plugin not properly initialized')
}, }
interfaceName: 'ProcessEmailsJob',
// Use the existing mailing service from context
await processEmailsJob(
job as { data: ProcessEmailsJobData },
{ req, mailingService: mailingContext.service }
)
return {
output: {
success: true,
message: 'Email queue processing completed successfully'
}
}
}, },
sendEmailJob, interfaceName: 'ProcessEmailsJob',
] },
} sendEmailJob,
]
export * from './processEmailsJob.js' export * from './processEmailsJob.js'
export * from './sendEmailTask.js' export * from './sendEmailTask.js'

View File

@@ -208,25 +208,22 @@ export const sendEmailJob = {
}) })
return { return {
success: true, output: {
emailId: email.id, success: true,
message: `Email queued successfully with ID: ${email.id}`, emailId: email.id,
mode: taskInput.templateSlug ? 'template' : 'direct', message: `Email queued successfully with ID: ${email.id}`,
templateSlug: taskInput.templateSlug || null, mode: taskInput.templateSlug ? 'template' : 'direct',
subject: subject, templateSlug: taskInput.templateSlug || null,
recipients: emailData.to?.length || 0, subject: subject,
scheduledAt: emailData.scheduledAt || null recipients: emailData.to?.length || 0,
scheduledAt: emailData.scheduledAt || null
}
} }
} catch (error) { } catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error' const errorMessage = error instanceof Error ? error.message : 'Unknown error'
return { throw new Error(`Failed to queue email: ${errorMessage}`)
success: false,
error: errorMessage,
templateSlug: taskInput.templateSlug,
message: `Failed to queue email: ${errorMessage}`
}
} }
} }
} }

View File

@@ -3,7 +3,7 @@ import { MailingPluginConfig, MailingContext } from './types/index.js'
import { MailingService } from './services/MailingService.js' import { MailingService } from './services/MailingService.js'
import { createEmailTemplatesCollection } from './collections/EmailTemplates.js' import { createEmailTemplatesCollection } from './collections/EmailTemplates.js'
import Emails from './collections/Emails.js' import Emails from './collections/Emails.js'
import { createMailingJobs, scheduleEmailsJob } from './jobs/index.js' import { mailingJobs, scheduleEmailsJob } from './jobs/index.js'
export const mailingPlugin = (pluginConfig: MailingPluginConfig) => (config: Config): Config => { export const mailingPlugin = (pluginConfig: MailingPluginConfig) => (config: Config): Config => {
@@ -14,14 +14,6 @@ export const mailingPlugin = (pluginConfig: MailingPluginConfig) => (config: Con
throw new Error('Invalid queue configuration: queue must be a non-empty string') throw new Error('Invalid queue configuration: queue must be a non-empty string')
} }
// Create a factory function that will provide the mailing service once initialized
const getMailingService = () => {
if (!mailingService) {
throw new Error('MailingService not yet initialized - this should only be called after plugin initialization')
}
return mailingService
}
let mailingService: MailingService
// Handle templates collection configuration // Handle templates collection configuration
const templatesConfig = pluginConfig.collections?.templates const templatesConfig = pluginConfig.collections?.templates
@@ -93,7 +85,7 @@ export const mailingPlugin = (pluginConfig: MailingPluginConfig) => (config: Con
...(config.jobs || {}), ...(config.jobs || {}),
tasks: [ tasks: [
...(config.jobs?.tasks || []), ...(config.jobs?.tasks || []),
// Jobs will be properly added after initialization ...mailingJobs,
], ],
}, },
onInit: async (payload: any) => { onInit: async (payload: any) => {
@@ -102,13 +94,7 @@ export const mailingPlugin = (pluginConfig: MailingPluginConfig) => (config: Con
} }
// Initialize mailing service with proper payload instance // Initialize mailing service with proper payload instance
mailingService = new MailingService(payload, pluginConfig) const mailingService = new MailingService(payload, pluginConfig)
// Add mailing jobs to payload's job system
const mailingJobs = createMailingJobs(mailingService)
mailingJobs.forEach(job => {
payload.jobs.tasks.push(job)
})
// Add mailing context to payload for developer access // Add mailing context to payload for developer access
;(payload as any).mailing = { ;(payload as any).mailing = {