diff --git a/docs/jobs-queue/queues.mdx b/docs/jobs-queue/queues.mdx
index ee5b7d6ddd..4e002b8bdc 100644
--- a/docs/jobs-queue/queues.mdx
+++ b/docs/jobs-queue/queues.mdx
@@ -25,7 +25,33 @@ Then, you could configure two different runner strategies:
## Executing jobs
-As mentioned above, you can queue jobs, but the jobs won't run unless a worker picks up your jobs and runs them. This can be done in two ways:
+As mentioned above, you can queue jobs, but the jobs won't run unless a worker picks up your jobs and runs them. This can be done in four ways:
+
+#### Cron jobs
+
+You can use the jobs.autoRun property to configure cron jobs:
+
+```ts
+export default buildConfig({
+ // Other configurations...
+ jobs: {
+ tasks: [
+ // your tasks here
+ ],
+ // autoRun can optionally be a function that receives payload as an argument
+ autoRun: [
+ {
+ cron: '0 * * * *', // every hour at minute 0
+ limit: 100, // limit jobs to process each run
+ queue: 'hourly', // name of the queue
+ },
+ // add as many cron jobs as you want
+ ],
+ },
+})
+```
+
+autoRun is intended for use with a dedicated server that is always running, and should not be used on serverless platforms like Vercel.
#### Endpoint
diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts
index 599c060681..4ccf6e9126 100644
--- a/packages/payload/src/index.ts
+++ b/packages/payload/src/index.ts
@@ -63,6 +63,8 @@ import type {
} from './types/index.js'
import type { TraverseFieldsCallback } from './utilities/traverseFields.js'
export type { FieldState } from './admin/forms/Form.js'
+import { Cron } from 'croner'
+
import type { TypeWithVersion } from './versions/types.js'
import { decrypt, encrypt } from './auth/crypto.js'
@@ -712,6 +714,25 @@ export class BasePayload {
await this.config.onInit(this)
}
}
+ if (this.config.jobs.autoRun) {
+ const DEFAULT_CRON = '* * * * *'
+ const DEFAULT_LIMIT = 10
+
+ const cronJobs =
+ 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 () => {
+ await this.jobs.run({
+ limit: cronConfig.limit ?? DEFAULT_LIMIT,
+ queue: cronConfig.queue,
+ })
+ })
+ }),
+ )
+ }
return this
}
diff --git a/packages/payload/src/queues/config/types/index.ts b/packages/payload/src/queues/config/types/index.ts
index 45d39025f4..fec620d9a1 100644
--- a/packages/payload/src/queues/config/types/index.ts
+++ b/packages/payload/src/queues/config/types/index.ts
@@ -1,8 +1,38 @@
import type { CollectionConfig } from '../../../index.js'
-import type { PayloadRequest } from '../../../types/index.js'
+import type { Payload, PayloadRequest } from '../../../types/index.js'
import type { TaskConfig } from './taskTypes.js'
import type { WorkflowConfig } from './workflowTypes.js'
+export type CronConfig = {
+ /**
+ * The cron schedule for the job.
+ * @default '* * * * *' (every minute).
+ *
+ * @example
+ * ┌───────────── minute (0 - 59)
+ * │ ┌───────────── hour (0 - 23)
+ * │ │ ┌───────────── day of the month (1 - 31)
+ * │ │ │ ┌───────────── month (1 - 12)
+ * │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
+ * │ │ │ │ │
+ * │ │ │ │ │
+ * - '0 * * * *' every hour at minute 0
+ * - '0 0 * * *' daily at midnight
+ * - '0 0 * * 0' weekly at midnight on Sundays
+ * - '0 0 1 * *' monthly at midnight on the 1st day of the month
+ * - '0/5 * * * *' every 5 minutes
+ */
+ cron?: string
+ /**
+ * The limit for the job. This can be overridden by the user. Defaults to 10.
+ */
+ limit?: number
+ /**
+ * The queue name for the job.
+ */
+ queue?: string
+}
+
export type RunJobAccessArgs = {
req: PayloadRequest
}
@@ -19,14 +49,18 @@ export type JobsConfig = {
*/
run?: RunJobAccess
}
- /**
- * Adds information about the parent job to the task log. This is useful for debugging and tracking the flow of tasks.
+ /** Adds information about the parent job to the task log. This is useful for debugging and tracking the flow of tasks.
*
* In 4.0, this will default to `true`.
*
* @default false
*/
addParentToTaskLog?: boolean
+ /**
+ * Queue cron jobs automatically on payload initialization.
+ * @remark this property should not be used on serverless platforms like Vercel
+ */
+ autoRun?: ((payload: Payload) => CronConfig[] | Promise) | CronConfig[]
/**
* Determine whether or not to delete a job after it has successfully completed.
*/