Adds a new `schedule` property to workflow and task configs that can be used to have Payload automatically _queue_ jobs following a certain _schedule_. Docs: https://payloadcms.com/docs/dynamic/jobs-queue/schedules?branch=feat/schedule-jobs ## API Example ```ts export default buildConfig({ // ... jobs: { // ... scheduler: 'manual', // Or `cron` if you're not using serverless. If `manual` is used, then user needs to set up running /api/payload-jobs/handleSchedules or payload.jobs.handleSchedules in regular intervals tasks: [ { schedule: [ { cron: '* * * * * *', queue: 'autorunSecond', // Hooks are optional hooks: { // Not an array, as providing and calling `defaultBeforeSchedule` would be more error-prone if this was an array beforeSchedule: async (args) => { // Handles verifying that there are no jobs already scheduled or processing. // You can override this behavior by not calling defaultBeforeSchedule, e.g. if you wanted // to allow a maximum of 3 scheduled jobs in the queue instead of 1, or add any additional conditions const result = await args.defaultBeforeSchedule(args) return { ...result, input: { message: 'This task runs every second', }, } }, afterSchedule: async (args) => { await args.defaultAfterSchedule(args) // Handles updating the payload-jobs-stats global args.req.payload.logger.info( 'EverySecond task scheduled: ' + (args.status === 'success' ? args.job.id : 'skipped or failed to schedule'), ) }, }, }, ], slug: 'EverySecond', inputSchema: [ { name: 'message', type: 'text', required: true, }, ], handler: ({ input, req }) => { req.payload.logger.info(input.message) return { output: {}, } }, } ] } }) ``` --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1210495300843759
177 lines
5.5 KiB
TypeScript
177 lines
5.5 KiB
TypeScript
import type { Config } from 'payload'
|
|
|
|
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
|
import { fileURLToPath } from 'node:url'
|
|
import path from 'path'
|
|
|
|
import { devUser } from '../credentials.js'
|
|
import { seed } from './seed.js'
|
|
import { CreateSimpleRetries0Task } from './tasks/CreateSimpleRetries0Task.js'
|
|
import { CreateSimpleRetriesUndefinedTask } from './tasks/CreateSimpleRetriesUndefinedTask.js'
|
|
import { CreateSimpleTask } from './tasks/CreateSimpleTask.js'
|
|
import { CreateSimpleWithDuplicateMessageTask } from './tasks/CreateSimpleWithDuplicateMessageTask.js'
|
|
import { ExternalTask } from './tasks/ExternalTask.js'
|
|
import { ReturnCustomErrorTask } from './tasks/ReturnCustomErrorTask.js'
|
|
import { ReturnErrorTask } from './tasks/ReturnErrorTask.js'
|
|
import { ThrowErrorTask } from './tasks/ThrowErrorTask.js'
|
|
import { UpdatePostStep2Task } from './tasks/UpdatePostStep2Task.js'
|
|
import { UpdatePostTask } from './tasks/UpdatePostTask.js'
|
|
import { externalWorkflow } from './workflows/externalWorkflow.js'
|
|
import { failsImmediatelyWorkflow } from './workflows/failsImmediately.js'
|
|
import { inlineTaskTestWorkflow } from './workflows/inlineTaskTest.js'
|
|
import { inlineTaskTestDelayedWorkflow } from './workflows/inlineTaskTestDelayed.js'
|
|
import { longRunningWorkflow } from './workflows/longRunning.js'
|
|
import { noRetriesSetWorkflow } from './workflows/noRetriesSet.js'
|
|
import { parallelTaskWorkflow } from './workflows/parallelTaskWorkflow.js'
|
|
import { retries0Workflow } from './workflows/retries0.js'
|
|
import { retriesBackoffTestWorkflow } from './workflows/retriesBackoffTest.js'
|
|
import { retriesRollbackTestWorkflow } from './workflows/retriesRollbackTest.js'
|
|
import { retriesTestWorkflow } from './workflows/retriesTest.js'
|
|
import { retriesWorkflowLevelTestWorkflow } from './workflows/retriesWorkflowLevelTest.js'
|
|
import { subTaskWorkflow } from './workflows/subTask.js'
|
|
import { subTaskFailsWorkflow } from './workflows/subTaskFails.js'
|
|
import { updatePostWorkflow } from './workflows/updatePost.js'
|
|
import { updatePostJSONWorkflow } from './workflows/updatePostJSON.js'
|
|
import { workflowAndTasksRetriesUndefinedWorkflow } from './workflows/workflowAndTasksRetriesUndefined.js'
|
|
import { workflowRetries2TasksRetries0Workflow } from './workflows/workflowRetries2TasksRetries0.js'
|
|
import { workflowRetries2TasksRetriesUndefinedWorkflow } from './workflows/workflowRetries2TasksRetriesUndefined.js'
|
|
|
|
const dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
|
|
// Needs to be a function to prevent object reference issues due to duplicative configs
|
|
export const getConfig: () => Partial<Config> = () => ({
|
|
collections: [
|
|
{
|
|
slug: 'posts',
|
|
admin: {
|
|
useAsTitle: 'title',
|
|
},
|
|
hooks: {
|
|
afterChange: [
|
|
async ({ req, doc, context }) => {
|
|
await req.payload.jobs.queue({
|
|
workflow: context.useJSONWorkflow ? 'updatePostJSONWorkflow' : 'updatePost',
|
|
input: {
|
|
post: doc.id,
|
|
message: 'hello',
|
|
},
|
|
req,
|
|
})
|
|
},
|
|
],
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'content',
|
|
type: 'richText',
|
|
},
|
|
{
|
|
name: 'jobStep1Ran',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'jobStep2Ran',
|
|
type: 'text',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
slug: 'simple',
|
|
admin: {
|
|
useAsTitle: 'title',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
admin: {
|
|
importMap: {
|
|
baseDir: path.resolve(dirname),
|
|
},
|
|
autoLogin: {
|
|
prefillOnly: true,
|
|
email: devUser.email,
|
|
password: devUser.password,
|
|
},
|
|
},
|
|
jobs: {
|
|
autoRun: [
|
|
{
|
|
silent: true,
|
|
// Every second
|
|
cron: '* * * * * *',
|
|
limit: 100,
|
|
queue: 'autorunSecond',
|
|
},
|
|
// add as many cron jobs as you want
|
|
],
|
|
shouldAutoRun: () => true,
|
|
jobsCollectionOverrides: ({ defaultJobsCollection }) => {
|
|
return {
|
|
...defaultJobsCollection,
|
|
admin: {
|
|
...(defaultJobsCollection?.admin || {}),
|
|
hidden: false,
|
|
},
|
|
}
|
|
},
|
|
processingOrder: {
|
|
queues: {
|
|
lifo: '-createdAt',
|
|
},
|
|
},
|
|
tasks: [
|
|
UpdatePostTask,
|
|
UpdatePostStep2Task,
|
|
CreateSimpleTask,
|
|
CreateSimpleRetriesUndefinedTask,
|
|
CreateSimpleRetries0Task,
|
|
CreateSimpleWithDuplicateMessageTask,
|
|
ExternalTask,
|
|
ThrowErrorTask,
|
|
ReturnErrorTask,
|
|
ReturnCustomErrorTask,
|
|
],
|
|
workflows: [
|
|
updatePostWorkflow,
|
|
updatePostJSONWorkflow,
|
|
retriesTestWorkflow,
|
|
retriesRollbackTestWorkflow,
|
|
retriesWorkflowLevelTestWorkflow,
|
|
noRetriesSetWorkflow,
|
|
retries0Workflow,
|
|
workflowAndTasksRetriesUndefinedWorkflow,
|
|
workflowRetries2TasksRetriesUndefinedWorkflow,
|
|
workflowRetries2TasksRetries0Workflow,
|
|
inlineTaskTestWorkflow,
|
|
failsImmediatelyWorkflow,
|
|
inlineTaskTestDelayedWorkflow,
|
|
externalWorkflow,
|
|
retriesBackoffTestWorkflow,
|
|
subTaskWorkflow,
|
|
subTaskFailsWorkflow,
|
|
longRunningWorkflow,
|
|
parallelTaskWorkflow,
|
|
],
|
|
},
|
|
editor: lexicalEditor(),
|
|
onInit: async (payload) => {
|
|
if (process.env.SEED_IN_CONFIG_ONINIT !== 'false') {
|
|
await seed(payload)
|
|
}
|
|
},
|
|
typescript: {
|
|
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
|
},
|
|
})
|