diff --git a/docs/jobs-queue/queues.mdx b/docs/jobs-queue/queues.mdx index 4e002b8bd..a60b4d37d 100644 --- a/docs/jobs-queue/queues.mdx +++ b/docs/jobs-queue/queues.mdx @@ -29,7 +29,7 @@ As mentioned above, you can queue jobs, but the jobs won't run unless a worker p #### Cron jobs -You can use the jobs.autoRun property to configure cron jobs: +You can use the `jobs.autoRun` property to configure cron jobs: ```ts export default buildConfig({ @@ -47,6 +47,12 @@ export default buildConfig({ }, // add as many cron jobs as you want ], + shouldAutoRun: async (payload) => { + // Tell Payload if it should run jobs or not. + // This function will be invoked each time Payload goes to pick up and run jobs. + // If this function ever returns false, the cron schedule will be stopped. + return true + } }, }) ``` diff --git a/packages/payload-cloud/src/plugin.ts b/packages/payload-cloud/src/plugin.ts index 21bf05571..7cf221746 100644 --- a/packages/payload-cloud/src/plugin.ts +++ b/packages/payload-cloud/src/plugin.ts @@ -105,8 +105,9 @@ export const payloadCloudPlugin = const DEFAULT_CRON_JOB = { cron: DEFAULT_CRON, limit: DEFAULT_LIMIT, - queue: 'default (every minute)', + queue: 'default', } + config.globals = [ ...(config.globals || []), { @@ -130,9 +131,33 @@ export const payloadCloudPlugin = const oldAutoRunCopy = config.jobs.autoRun ?? [] + const hasExistingAutorun = Boolean(config.jobs.autoRun) + + const newShouldAutoRun = async (payload: Payload) => { + if (process.env.PAYLOAD_CLOUD_JOBS_INSTANCE) { + const retrievedGlobal = await payload.findGlobal({ + slug: 'payload-cloud-instance', + }) + + if (retrievedGlobal.instance === process.env.PAYLOAD_CLOUD_JOBS_INSTANCE) { + return true + } else { + process.env.PAYLOAD_CLOUD_JOBS_INSTANCE = '' + } + } + + return false + } + + if (!config.jobs.shouldAutoRun) { + config.jobs.shouldAutoRun = newShouldAutoRun + } + const newAutoRun = async (payload: Payload) => { const instance = generateRandomString() + process.env.PAYLOAD_CLOUD_JOBS_INSTANCE = instance + await payload.updateGlobal({ slug: 'payload-cloud-instance', data: { @@ -140,16 +165,7 @@ export const payloadCloudPlugin = }, }) - await waitRandomTime() - - const cloudInstance = await payload.findGlobal({ - slug: 'payload-cloud-instance', - }) - - if (cloudInstance.instance !== instance) { - return [] - } - if (!config.jobs?.autoRun) { + if (!hasExistingAutorun) { return [DEFAULT_CRON_JOB] } @@ -160,11 +176,3 @@ export const payloadCloudPlugin = return config } - -function waitRandomTime(): Promise { - const min = 1000 // 1 second in milliseconds - const max = 5000 // 5 seconds in milliseconds - const randomTime = Math.floor(Math.random() * (max - min + 1)) + min - - return new Promise((resolve) => setTimeout(resolve, randomTime)) -} diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 366c571b2..bd4879575 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -729,9 +729,20 @@ export class BasePayload { typeof this.config.jobs.autoRun === 'function' ? await this.config.jobs.autoRun(this) : this.config.jobs.autoRun + await Promise.all( cronJobs.map((cronConfig) => { - new Cron(cronConfig.cron ?? DEFAULT_CRON, async () => { + const job = new Cron(cronConfig.cron ?? DEFAULT_CRON, async () => { + if (typeof this.config.jobs.shouldAutoRun === 'function') { + const shouldAutoRun = await this.config.jobs.shouldAutoRun(this) + + if (!shouldAutoRun) { + job.stop() + + return false + } + } + await this.jobs.run({ limit: cronConfig.limit ?? DEFAULT_LIMIT, queue: cronConfig.queue, diff --git a/packages/payload/src/queues/config/types/index.ts b/packages/payload/src/queues/config/types/index.ts index fec620d9a..d3b1836c5 100644 --- a/packages/payload/src/queues/config/types/index.ts +++ b/packages/payload/src/queues/config/types/index.ts @@ -76,6 +76,13 @@ export type JobsConfig = { * a new collection. */ jobsCollectionOverrides?: (args: { defaultJobsCollection: CollectionConfig }) => CollectionConfig + /** + * A function that will be executed before Payload picks up jobs which are configured by the `jobs.autorun` function. + * If this function returns true, jobs will be queried and picked up. If it returns false, jobs will not be run. + * @param payload + * @returns boolean + */ + shouldAutoRun?: (payload: Payload) => boolean | Promise /** * Define all possible tasks here */