diff --git a/docs/jobs-queue/queues.mdx b/docs/jobs-queue/queues.mdx index b67014c56..6b0172df2 100644 --- a/docs/jobs-queue/queues.mdx +++ b/docs/jobs-queue/queues.mdx @@ -51,7 +51,7 @@ export default buildConfig({ // add as many cron jobs as you want ], shouldAutoRun: async (payload) => { - // Tell Payload if it should run jobs or not. + // Tell Payload if it should run jobs or not. This function is optional and will return true by default. // 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/next/src/auth/login.ts b/packages/next/src/auth/login.ts index 5bed900a9..9b5a7cb74 100644 --- a/packages/next/src/auth/login.ts +++ b/packages/next/src/auth/login.ts @@ -27,7 +27,7 @@ export async function login({ collection, config, email, password, username }: L token?: string user: any }> { - const payload = await getPayload({ config }) + const payload = await getPayload({ config, cron: true }) const authConfig = payload.collections[collection]?.config.auth diff --git a/packages/next/src/auth/logout.ts b/packages/next/src/auth/logout.ts index 192e29358..f1684dd50 100644 --- a/packages/next/src/auth/logout.ts +++ b/packages/next/src/auth/logout.ts @@ -14,7 +14,7 @@ export async function logout({ allSessions?: boolean config: Promise | SanitizedConfig }) { - const payload = await getPayload({ config }) + const payload = await getPayload({ config, cron: true }) const headers = await nextHeaders() const authResult = await payload.auth({ headers }) diff --git a/packages/next/src/auth/refresh.ts b/packages/next/src/auth/refresh.ts index 9ece3e97c..05fc5964d 100644 --- a/packages/next/src/auth/refresh.ts +++ b/packages/next/src/auth/refresh.ts @@ -9,7 +9,7 @@ import { getExistingAuthToken } from '../utilities/getExistingAuthToken.js' import { setPayloadAuthCookie } from '../utilities/setPayloadAuthCookie.js' export async function refresh({ config }: { config: any }) { - const payload = await getPayload({ config }) + const payload = await getPayload({ config, cron: true }) const headers = await nextHeaders() const result = await payload.auth({ headers }) diff --git a/packages/next/src/utilities/initReq.ts b/packages/next/src/utilities/initReq.ts index 62c6cd98d..aa9b29b71 100644 --- a/packages/next/src/utilities/initReq.ts +++ b/packages/next/src/utilities/initReq.ts @@ -66,7 +66,7 @@ export const initReq = async function ({ const partialResult = await partialReqCache.get(async () => { const config = await configPromise - const payload = await getPayload({ config, importMap }) + const payload = await getPayload({ config, cron: true, importMap }) const languageCode = getRequestLanguage({ config, cookies, diff --git a/packages/payload/src/bin/index.ts b/packages/payload/src/bin/index.ts index 81d06a78b..b1b973d0e 100755 --- a/packages/payload/src/bin/index.ts +++ b/packages/payload/src/bin/index.ts @@ -107,7 +107,7 @@ export const bin = async () => { } if (script === 'jobs:run') { - const payload = await getPayload({ config }) + const payload = await getPayload({ config }) // Do not setup crons here - this bin script can set up its own crons const limit = args.limit ? parseInt(args.limit, 10) : undefined const queue = args.queue ? args.queue : undefined const allQueues = !!args.allQueues diff --git a/packages/payload/src/config/types.ts b/packages/payload/src/config/types.ts index ee1b3bc25..fdd2e460f 100644 --- a/packages/payload/src/config/types.ts +++ b/packages/payload/src/config/types.ts @@ -257,6 +257,13 @@ export type InitOptions = { * and the backend functionality */ config: Promise | SanitizedConfig + /** + * If set to `true`, payload will initialize crons for things like autorunning jobs on initialization. + * + * @default false + */ + cron?: boolean + /** * Disable connect to the database on init */ @@ -268,7 +275,6 @@ export type InitOptions = { disableOnInit?: boolean importMap?: ImportMap - /** * A function that is called immediately following startup that receives the Payload instance as it's only argument. */ diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index b768b4bde..0c2ea2680 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -836,7 +836,7 @@ export class BasePayload { throw error } - if (this.config.jobs.enabled && this.config.jobs.autoRun && !isNextBuild()) { + if (this.config.jobs.enabled && this.config.jobs.autoRun && !isNextBuild() && options.cron) { const DEFAULT_CRON = '* * * * *' const DEFAULT_LIMIT = 10 @@ -974,7 +974,7 @@ export const reload = async ( } export const getPayload = async ( - options: Pick, + options: Pick, ): Promise => { if (!options?.config) { throw new Error('Error: the payload config is required for getPayload to work.') @@ -1109,6 +1109,8 @@ export { generateImportMap } from './bin/generateImportMap/index.js' export type { ImportMap } from './bin/generateImportMap/index.js' export { genImportMapIterateFields } from './bin/generateImportMap/iterateFields.js' +export { migrate as migrateCLI } from './bin/migrate.js' + export { type ClientCollectionConfig, createClientCollectionConfig, @@ -1155,7 +1157,6 @@ export type { } from './collections/config/types.js' export type { CompoundIndex } from './collections/config/types.js' - export type { SanitizedCompoundIndex } from './collections/config/types.js' export { createDataloaderCacheKey, getDataLoader } from './collections/dataloader.js' export { countOperation } from './collections/operations/count.js' @@ -1171,6 +1172,7 @@ export { findVersionsOperation } from './collections/operations/findVersions.js' export { restoreVersionOperation } from './collections/operations/restoreVersion.js' export { updateOperation } from './collections/operations/update.js' export { updateByIDOperation } from './collections/operations/updateByID.js' + export { buildConfig } from './config/build.js' export { @@ -1180,7 +1182,6 @@ export { serverOnlyConfigProperties, type UnsanitizedClientConfig, } from './config/client.js' - export { defaults } from './config/defaults.js' export { type OrderableEndpointBody } from './config/orderable/index.js' export { sanitizeConfig } from './config/sanitize.js' @@ -1297,10 +1298,11 @@ export { ValidationError, ValidationErrorName, } from './errors/index.js' -export type { ValidationFieldError } from './errors/index.js' +export type { ValidationFieldError } from './errors/index.js' export { baseBlockFields } from './fields/baseFields/baseBlockFields.js' export { baseIDField } from './fields/baseFields/baseIDField.js' + export { createClientField, createClientFields, @@ -1308,10 +1310,10 @@ export { type ServerOnlyFieldProperties, } from './fields/config/client.js' -export { sanitizeFields } from './fields/config/sanitize.js' - export interface FieldCustom extends Record {} +export { sanitizeFields } from './fields/config/sanitize.js' + export type { AdminClient, ArrayField, @@ -1421,14 +1423,13 @@ export type { } from './fields/config/types.js' export { getDefaultValue } from './fields/getDefaultValue.js' - export { traverseFields as afterChangeTraverseFields } from './fields/hooks/afterChange/traverseFields.js' export { promise as afterReadPromise } from './fields/hooks/afterRead/promise.js' export { traverseFields as afterReadTraverseFields } from './fields/hooks/afterRead/traverseFields.js' export { traverseFields as beforeChangeTraverseFields } from './fields/hooks/beforeChange/traverseFields.js' export { traverseFields as beforeValidateTraverseFields } from './fields/hooks/beforeValidate/traverseFields.js' -export { sortableFieldTypes } from './fields/sortableFieldTypes.js' +export { sortableFieldTypes } from './fields/sortableFieldTypes.js' export { validations } from './fields/validations.js' export type { ArrayFieldValidation, @@ -1481,8 +1482,8 @@ export type { GlobalConfig, SanitizedGlobalConfig, } from './globals/config/types.js' -export { docAccessOperation as docAccessOperationGlobal } from './globals/operations/docAccess.js' +export { docAccessOperation as docAccessOperationGlobal } from './globals/operations/docAccess.js' export { findOneOperation } from './globals/operations/findOne.js' export { findVersionByIDOperation as findVersionByIDOperationGlobal } from './globals/operations/findVersionByID.js' export { findVersionsOperation as findVersionsOperationGlobal } from './globals/operations/findVersions.js' @@ -1505,8 +1506,8 @@ export type { } from './preferences/types.js' export type { QueryPreset } from './query-presets/types.js' export { jobAfterRead } from './queues/config/index.js' -export type { JobsConfig, RunJobAccess, RunJobAccessArgs } from './queues/config/types/index.js' +export type { JobsConfig, RunJobAccess, RunJobAccessArgs } from './queues/config/types/index.js' export type { RunInlineTaskFunction, RunTaskFunction, @@ -1530,14 +1531,14 @@ export type { WorkflowHandler, WorkflowTypes, } from './queues/config/types/workflowTypes.js' -export { importHandlerPath } from './queues/operations/runJobs/runJob/importHandlerPath.js' +export { importHandlerPath } from './queues/operations/runJobs/runJob/importHandlerPath.js' export { getLocalI18n } from './translations/getLocalI18n.js' export * from './types/index.js' export { getFileByPath } from './uploads/getFileByPath.js' export { _internal_safeFetchGlobal } from './uploads/safeFetch.js' -export type * from './uploads/types.js' +export type * from './uploads/types.js' export { addDataAndFileToRequest } from './utilities/addDataAndFileToRequest.js' export { addLocalesToRequestFromData, sanitizeLocales } from './utilities/addLocalesToRequest.js' export { commitTransaction } from './utilities/commitTransaction.js' @@ -1609,8 +1610,8 @@ export { versionDefaults } from './versions/defaults.js' export { deleteCollectionVersions } from './versions/deleteCollectionVersions.js' export { appendVersionToQueryKey } from './versions/drafts/appendVersionToQueryKey.js' export { getQueryDraftsSort } from './versions/drafts/getQueryDraftsSort.js' -export { enforceMaxVersions } from './versions/enforceMaxVersions.js' +export { enforceMaxVersions } from './versions/enforceMaxVersions.js' export { getLatestCollectionVersion } from './versions/getLatestCollectionVersion.js' export { getLatestGlobalVersion } from './versions/getLatestGlobalVersion.js' export { saveVersion } from './versions/saveVersion.js' diff --git a/packages/payload/src/queues/config/types/index.ts b/packages/payload/src/queues/config/types/index.ts index 2e6eafc72..6bf730f44 100644 --- a/packages/payload/src/queues/config/types/index.ts +++ b/packages/payload/src/queues/config/types/index.ts @@ -121,6 +121,7 @@ export type JobsConfig = { /** * 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. + * @default undefined - if this function is not defined, jobs will be run - as if () => true was passed. * @param payload * @returns boolean */ diff --git a/packages/payload/src/utilities/createPayloadRequest.ts b/packages/payload/src/utilities/createPayloadRequest.ts index f87550cf7..ac262ce8a 100644 --- a/packages/payload/src/utilities/createPayloadRequest.ts +++ b/packages/payload/src/utilities/createPayloadRequest.ts @@ -27,7 +27,7 @@ export const createPayloadRequest = async ({ request, }: Args): Promise => { const cookies = parseCookies(request.headers) - const payload = await getPayload({ config: configPromise }) + const payload = await getPayload({ config: configPromise, cron: true }) const { config } = payload const localization = config.localization diff --git a/packages/payload/src/utilities/routeError.ts b/packages/payload/src/utilities/routeError.ts index ce435a25e..1d66ed318 100644 --- a/packages/payload/src/utilities/routeError.ts +++ b/packages/payload/src/utilities/routeError.ts @@ -39,7 +39,7 @@ export const routeError = async ({ if (!payload) { try { - payload = await getPayload({ config: configArg }) + payload = await getPayload({ config: configArg, cron: true }) } catch (ignore) { return Response.json( { diff --git a/test/helpers/initPayloadInt.ts b/test/helpers/initPayloadInt.ts index 184db198a..2801b5985 100644 --- a/test/helpers/initPayloadInt.ts +++ b/test/helpers/initPayloadInt.ts @@ -29,7 +29,7 @@ export async function initPayloadInt { } }) }) + +describe('Queues - CLI', () => { + let config: SanitizedConfig + beforeAll(async () => { + ;({ config } = await initPayloadInt(dirname, undefined, false)) + }) + it('can run migrate CLI without jobs attempting to run', async () => { + await migrateCLI({ + config, + parsedArgs: { + _: ['migrate'], + }, + }) + + // Wait 3 seconds to let potential autorun crons trigger + await new Promise((resolve) => setTimeout(resolve, 3000)) + + // Expect no errors. Previously, this would throw an "error: relation "payload_jobs" does not exist" error + expect(true).toBe(true) + }) +})