@depup/payload 3.82.1-depup.0 → 3.86.0-depup.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -13
- package/bin.js +11 -0
- package/changes.json +25 -17
- package/dist/admin/fields/Row.d.ts +2 -2
- package/dist/admin/fields/Row.d.ts.map +1 -1
- package/dist/admin/fields/Row.js.map +1 -1
- package/dist/admin/forms/Field.d.ts +1 -3
- package/dist/admin/forms/Field.d.ts.map +1 -1
- package/dist/admin/forms/Field.js.map +1 -1
- package/dist/admin/views/index.d.ts +5 -1
- package/dist/admin/views/index.d.ts.map +1 -1
- package/dist/admin/views/index.js.map +1 -1
- package/dist/bin/generateImportMap/index.d.ts.map +1 -1
- package/dist/bin/generateImportMap/index.js +1 -0
- package/dist/bin/generateImportMap/index.js.map +1 -1
- package/dist/bin/generateImportMap/iterateCollections.d.ts.map +1 -1
- package/dist/bin/generateImportMap/iterateCollections.js +11 -0
- package/dist/bin/generateImportMap/iterateCollections.js.map +1 -1
- package/dist/bin/index.d.ts.map +1 -1
- package/dist/bin/index.js +3 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/collections/config/sanitize.d.ts +5 -0
- package/dist/collections/config/sanitize.d.ts.map +1 -1
- package/dist/collections/config/sanitize.js +21 -0
- package/dist/collections/config/sanitize.js.map +1 -1
- package/dist/collections/config/sanitize.spec.js +120 -0
- package/dist/collections/config/sanitize.spec.js.map +1 -0
- package/dist/collections/config/types.d.ts +24 -1
- package/dist/collections/config/types.d.ts.map +1 -1
- package/dist/collections/config/types.js.map +1 -1
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +1 -0
- package/dist/collections/operations/create.js.map +1 -1
- package/dist/collections/operations/delete.d.ts.map +1 -1
- package/dist/collections/operations/delete.js +3 -0
- package/dist/collections/operations/delete.js.map +1 -1
- package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
- package/dist/collections/operations/restoreVersion.js +1 -0
- package/dist/collections/operations/restoreVersion.js.map +1 -1
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +7 -2
- package/dist/collections/operations/update.js.map +1 -1
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.d.ts +9 -0
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.d.ts.map +1 -0
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.js +170 -0
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.js.map +1 -0
- package/dist/collections/operations/utilities/update.d.ts.map +1 -1
- package/dist/collections/operations/utilities/update.js +16 -8
- package/dist/collections/operations/utilities/update.js.map +1 -1
- package/dist/config/build.js +5 -4
- package/dist/config/build.js.map +1 -1
- package/dist/config/definePlugin.d.ts +41 -0
- package/dist/config/definePlugin.d.ts.map +1 -0
- package/dist/config/definePlugin.js +34 -0
- package/dist/config/definePlugin.js.map +1 -0
- package/dist/config/orderable/index.d.ts.map +1 -1
- package/dist/config/orderable/index.js +23 -0
- package/dist/config/orderable/index.js.map +1 -1
- package/dist/config/types.d.ts +30 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/email/normalizeSendEmailOptions.d.ts +13 -0
- package/dist/email/normalizeSendEmailOptions.d.ts.map +1 -0
- package/dist/email/normalizeSendEmailOptions.js +20 -0
- package/dist/email/normalizeSendEmailOptions.js.map +1 -0
- package/dist/email/types.d.ts +7 -2
- package/dist/email/types.d.ts.map +1 -1
- package/dist/email/types.js.map +1 -1
- package/dist/errors/APIError.d.ts +2 -1
- package/dist/errors/APIError.d.ts.map +1 -1
- package/dist/errors/APIError.js +1 -3
- package/dist/errors/APIError.js.map +1 -1
- package/dist/errors/ValidationError.d.ts +3 -1
- package/dist/errors/ValidationError.d.ts.map +1 -1
- package/dist/errors/ValidationError.js +1 -3
- package/dist/errors/ValidationError.js.map +1 -1
- package/dist/fields/config/sanitize.d.ts.map +1 -1
- package/dist/fields/config/sanitize.js +3 -0
- package/dist/fields/config/sanitize.js.map +1 -1
- package/dist/fields/config/sanitize.spec.js +66 -0
- package/dist/fields/config/sanitize.spec.js.map +1 -1
- package/dist/fields/config/types.d.ts +3 -2
- package/dist/fields/config/types.d.ts.map +1 -1
- package/dist/fields/config/types.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/promise.js +2 -2
- package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
- package/dist/globals/operations/restoreVersion.d.ts.map +1 -1
- package/dist/globals/operations/restoreVersion.js +1 -0
- package/dist/globals/operations/restoreVersion.js.map +1 -1
- package/dist/index.bundled.d.ts +484 -115
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/queues/config/collection.d.ts.map +1 -1
- package/dist/queues/config/collection.js +0 -1
- package/dist/queues/config/collection.js.map +1 -1
- package/dist/queues/endpoints/run.d.ts.map +1 -1
- package/dist/queues/endpoints/run.js +0 -3
- package/dist/queues/endpoints/run.js.map +1 -1
- package/dist/queues/errors/calculateBackoffWaitUntil.d.ts.map +1 -1
- package/dist/queues/errors/calculateBackoffWaitUntil.js +5 -13
- package/dist/queues/errors/calculateBackoffWaitUntil.js.map +1 -1
- package/dist/queues/errors/handleWorkflowError.d.ts.map +1 -1
- package/dist/queues/errors/handleWorkflowError.js +9 -1
- package/dist/queues/errors/handleWorkflowError.js.map +1 -1
- package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts.map +1 -1
- package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js +2 -1
- package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js.map +1 -1
- package/dist/queues/operations/handleSchedules/defaultAfterSchedule.js +1 -1
- package/dist/queues/operations/handleSchedules/defaultAfterSchedule.js.map +1 -1
- package/dist/queues/operations/handleSchedules/index.d.ts.map +1 -1
- package/dist/queues/operations/handleSchedules/index.js +4 -1
- package/dist/queues/operations/handleSchedules/index.js.map +1 -1
- package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/index.js +44 -26
- package/dist/queues/operations/runJobs/index.js.map +1 -1
- package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJSONJob/index.js +1 -0
- package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
- package/dist/queues/utilities/updateJob.d.ts.map +1 -1
- package/dist/queues/utilities/updateJob.js +2 -1
- package/dist/queues/utilities/updateJob.js.map +1 -1
- package/dist/types/index.d.ts +4 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/uploads/checkFileAccess.d.ts.map +1 -1
- package/dist/uploads/checkFileAccess.js +30 -9
- package/dist/uploads/checkFileAccess.js.map +1 -1
- package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
- package/dist/uploads/checkFileRestrictions.js +48 -8
- package/dist/uploads/checkFileRestrictions.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/isEligibleRequest.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/isEligibleRequest.js +2 -1
- package/dist/uploads/fetchAPI-multipart/isEligibleRequest.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/isEligibleRequest.spec.js +29 -0
- package/dist/uploads/fetchAPI-multipart/isEligibleRequest.spec.js.map +1 -0
- package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.js +11 -2
- package/dist/uploads/fetchAPI-multipart/processMultipart.js.map +1 -1
- package/dist/uploads/generateFileData.d.ts +2 -1
- package/dist/uploads/generateFileData.d.ts.map +1 -1
- package/dist/uploads/generateFileData.js +5 -2
- package/dist/uploads/generateFileData.js.map +1 -1
- package/dist/uploads/getSafeFilename.d.ts +9 -4
- package/dist/uploads/getSafeFilename.d.ts.map +1 -1
- package/dist/uploads/getSafeFilename.js +5 -5
- package/dist/uploads/getSafeFilename.js.map +1 -1
- package/dist/uploads/types.d.ts +4 -0
- package/dist/uploads/types.d.ts.map +1 -1
- package/dist/uploads/types.js.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.js +16 -3
- package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.spec.js +41 -0
- package/dist/utilities/addDataAndFileToRequest.spec.js.map +1 -0
- package/dist/utilities/createPayloadRequest.d.ts.map +1 -1
- package/dist/utilities/createPayloadRequest.js +1 -0
- package/dist/utilities/createPayloadRequest.js.map +1 -1
- package/dist/utilities/filterDataToSelectedLocales.d.ts.map +1 -1
- package/dist/utilities/filterDataToSelectedLocales.js +74 -31
- package/dist/utilities/filterDataToSelectedLocales.js.map +1 -1
- package/dist/utilities/filterDataToSelectedLocales.spec.js +337 -0
- package/dist/utilities/filterDataToSelectedLocales.spec.js.map +1 -1
- package/dist/utilities/formatErrors.d.ts +1 -1
- package/dist/utilities/formatErrors.d.ts.map +1 -1
- package/dist/utilities/formatErrors.js +4 -7
- package/dist/utilities/formatErrors.js.map +1 -1
- package/dist/utilities/formatErrors.spec.js +101 -0
- package/dist/utilities/formatErrors.spec.js.map +1 -0
- package/dist/utilities/isURLAllowed.d.ts.map +1 -1
- package/dist/utilities/isURLAllowed.js +9 -3
- package/dist/utilities/isURLAllowed.js.map +1 -1
- package/dist/utilities/isURLAllowed.spec.js +78 -0
- package/dist/utilities/isURLAllowed.spec.js.map +1 -0
- package/dist/utilities/parseParams/index.d.ts +1 -1
- package/dist/utilities/parseParams/index.d.ts.map +1 -1
- package/dist/utilities/parseParams/index.js +3 -0
- package/dist/utilities/parseParams/index.js.map +1 -1
- package/dist/utilities/parseParams/index.spec.js +24 -0
- package/dist/utilities/parseParams/index.spec.js.map +1 -1
- package/dist/utilities/profiling.d.ts +12 -0
- package/dist/utilities/profiling.d.ts.map +1 -0
- package/dist/utilities/profiling.js +56 -0
- package/dist/utilities/profiling.js.map +1 -0
- package/dist/utilities/profiling.spec.js +53 -0
- package/dist/utilities/profiling.spec.js.map +1 -0
- package/dist/versions/saveVersion.js +1 -1
- package/dist/versions/saveVersion.js.map +1 -1
- package/dist/versions/schedule/job.d.ts.map +1 -1
- package/dist/versions/schedule/job.js +4 -1
- package/dist/versions/schedule/job.js.map +1 -1
- package/dist/versions/updateLatestVersion.d.ts.map +1 -1
- package/dist/versions/updateLatestVersion.js +55 -8
- package/dist/versions/updateLatestVersion.js.map +1 -1
- package/package.json +42 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/queues/endpoints/run.ts"],"sourcesContent":["import type { Endpoint } from '../../config/types.js'\nimport type { SanitizedJobsConfig } from '../config/types/index.js'\n\nimport { runJobs, type RunJobsArgs } from '../operations/runJobs/index.js'\n\n/**\n * /api/payload-jobs/run endpoint\n *\n * This endpoint is GET instead of POST to allow it to be used in a Vercel Cron.\n */\nexport const runJobsEndpoint: Endpoint = {\n handler: async (req) => {\n const jobsConfig = req.payload.config.jobs\n\n if (!configHasJobs(jobsConfig)) {\n return Response.json(\n {\n message: 'No jobs to run.',\n },\n { status: 200 },\n )\n }\n\n const accessFn = jobsConfig.access?.run ?? (() => true)\n\n const hasAccess = await accessFn({ req })\n\n if (!hasAccess) {\n return Response.json(\n {\n message: req.i18n.t('error:unauthorized'),\n },\n { status: 401 },\n )\n }\n\n const {\n allQueues,\n disableScheduling: disableSchedulingParam,\n limit,\n queue,\n silent: silentParam,\n } = req.query as {\n allQueues?: 'false' | 'true'\n disableScheduling?: 'false' | 'true'\n limit?: number\n queue?: string\n silent?: string\n }\n\n const silent = silentParam === 'true'\n\n const shouldHandleSchedules = disableSchedulingParam !== 'true'\n\n const runAllQueues = allQueues && !(typeof allQueues === 'string' && allQueues === 'false')\n\n if (shouldHandleSchedules && jobsConfig.scheduling) {\n // If should handle schedules and schedules are defined\n await req.payload.jobs.handleSchedules({ allQueues: runAllQueues, queue, req })\n }\n\n const runJobsArgs: RunJobsArgs = {\n queue,\n req,\n // Access is validated above, so it's safe to override here\n allQueues: runAllQueues,\n overrideAccess: true,\n silent,\n }\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/queues/endpoints/run.ts"],"sourcesContent":["import type { Endpoint } from '../../config/types.js'\nimport type { SanitizedJobsConfig } from '../config/types/index.js'\n\nimport { runJobs, type RunJobsArgs } from '../operations/runJobs/index.js'\n\n/**\n * /api/payload-jobs/run endpoint\n *\n * This endpoint is GET instead of POST to allow it to be used in a Vercel Cron.\n */\nexport const runJobsEndpoint: Endpoint = {\n handler: async (req) => {\n const jobsConfig = req.payload.config.jobs\n\n if (!configHasJobs(jobsConfig)) {\n return Response.json(\n {\n message: 'No jobs to run.',\n },\n { status: 200 },\n )\n }\n\n const accessFn = jobsConfig.access?.run ?? (() => true)\n\n const hasAccess = await accessFn({ req })\n\n if (!hasAccess) {\n return Response.json(\n {\n message: req.i18n.t('error:unauthorized'),\n },\n { status: 401 },\n )\n }\n\n const {\n allQueues,\n disableScheduling: disableSchedulingParam,\n limit,\n queue,\n silent: silentParam,\n } = req.query as {\n allQueues?: 'false' | 'true'\n disableScheduling?: 'false' | 'true'\n limit?: number\n queue?: string\n silent?: string\n }\n\n const silent = silentParam === 'true'\n\n const shouldHandleSchedules = disableSchedulingParam !== 'true'\n\n const runAllQueues = allQueues && !(typeof allQueues === 'string' && allQueues === 'false')\n\n if (shouldHandleSchedules && jobsConfig.scheduling) {\n // If should handle schedules and schedules are defined\n await req.payload.jobs.handleSchedules({ allQueues: runAllQueues, queue, req })\n }\n\n const runJobsArgs: RunJobsArgs = {\n queue,\n req,\n // Access is validated above, so it's safe to override here\n allQueues: runAllQueues,\n overrideAccess: true,\n silent,\n }\n\n const parsedLimit = Number(limit)\n if (!isNaN(parsedLimit)) {\n runJobsArgs.limit = parsedLimit\n }\n\n let noJobsRemaining = false\n let remainingJobsFromQueried = 0\n try {\n const result = await runJobs(runJobsArgs)\n noJobsRemaining = !!result.noJobsRemaining\n remainingJobsFromQueried = result.remainingJobsFromQueried\n } catch (err) {\n req.payload.logger.error({\n err,\n msg: 'There was an error running jobs:',\n queue: runJobsArgs.queue,\n })\n\n return Response.json(\n {\n message: req.i18n.t('error:unknown'),\n noJobsRemaining: true,\n remainingJobsFromQueried,\n },\n { status: 500 },\n )\n }\n\n return Response.json(\n {\n message: req.i18n.t('general:success'),\n noJobsRemaining,\n remainingJobsFromQueried,\n },\n { status: 200 },\n )\n },\n method: 'get',\n path: '/run',\n}\n\nexport const configHasJobs = (jobsConfig: SanitizedJobsConfig): boolean => {\n return Boolean(jobsConfig.tasks?.length || jobsConfig.workflows?.length)\n}\n"],"names":["runJobs","runJobsEndpoint","handler","req","jobsConfig","payload","config","jobs","configHasJobs","Response","json","message","status","accessFn","access","run","hasAccess","i18n","t","allQueues","disableScheduling","disableSchedulingParam","limit","queue","silent","silentParam","query","shouldHandleSchedules","runAllQueues","scheduling","handleSchedules","runJobsArgs","overrideAccess","parsedLimit","Number","isNaN","noJobsRemaining","remainingJobsFromQueried","result","err","logger","error","msg","method","path","Boolean","tasks","length","workflows"],"mappings":"AAGA,SAASA,OAAO,QAA0B,iCAAgC;AAE1E;;;;CAIC,GACD,OAAO,MAAMC,kBAA4B;IACvCC,SAAS,OAAOC;QACd,MAAMC,aAAaD,IAAIE,OAAO,CAACC,MAAM,CAACC,IAAI;QAE1C,IAAI,CAACC,cAAcJ,aAAa;YAC9B,OAAOK,SAASC,IAAI,CAClB;gBACEC,SAAS;YACX,GACA;gBAAEC,QAAQ;YAAI;QAElB;QAEA,MAAMC,WAAWT,WAAWU,MAAM,EAAEC,OAAQ,CAAA,IAAM,IAAG;QAErD,MAAMC,YAAY,MAAMH,SAAS;YAAEV;QAAI;QAEvC,IAAI,CAACa,WAAW;YACd,OAAOP,SAASC,IAAI,CAClB;gBACEC,SAASR,IAAIc,IAAI,CAACC,CAAC,CAAC;YACtB,GACA;gBAAEN,QAAQ;YAAI;QAElB;QAEA,MAAM,EACJO,SAAS,EACTC,mBAAmBC,sBAAsB,EACzCC,KAAK,EACLC,KAAK,EACLC,QAAQC,WAAW,EACpB,GAAGtB,IAAIuB,KAAK;QAQb,MAAMF,SAASC,gBAAgB;QAE/B,MAAME,wBAAwBN,2BAA2B;QAEzD,MAAMO,eAAeT,aAAa,CAAE,CAAA,OAAOA,cAAc,YAAYA,cAAc,OAAM;QAEzF,IAAIQ,yBAAyBvB,WAAWyB,UAAU,EAAE;YAClD,uDAAuD;YACvD,MAAM1B,IAAIE,OAAO,CAACE,IAAI,CAACuB,eAAe,CAAC;gBAAEX,WAAWS;gBAAcL;gBAAOpB;YAAI;QAC/E;QAEA,MAAM4B,cAA2B;YAC/BR;YACApB;YACA,2DAA2D;YAC3DgB,WAAWS;YACXI,gBAAgB;YAChBR;QACF;QAEA,MAAMS,cAAcC,OAAOZ;QAC3B,IAAI,CAACa,MAAMF,cAAc;YACvBF,YAAYT,KAAK,GAAGW;QACtB;QAEA,IAAIG,kBAAkB;QACtB,IAAIC,2BAA2B;QAC/B,IAAI;YACF,MAAMC,SAAS,MAAMtC,QAAQ+B;YAC7BK,kBAAkB,CAAC,CAACE,OAAOF,eAAe;YAC1CC,2BAA2BC,OAAOD,wBAAwB;QAC5D,EAAE,OAAOE,KAAK;YACZpC,IAAIE,OAAO,CAACmC,MAAM,CAACC,KAAK,CAAC;gBACvBF;gBACAG,KAAK;gBACLnB,OAAOQ,YAAYR,KAAK;YAC1B;YAEA,OAAOd,SAASC,IAAI,CAClB;gBACEC,SAASR,IAAIc,IAAI,CAACC,CAAC,CAAC;gBACpBkB,iBAAiB;gBACjBC;YACF,GACA;gBAAEzB,QAAQ;YAAI;QAElB;QAEA,OAAOH,SAASC,IAAI,CAClB;YACEC,SAASR,IAAIc,IAAI,CAACC,CAAC,CAAC;YACpBkB;YACAC;QACF,GACA;YAAEzB,QAAQ;QAAI;IAElB;IACA+B,QAAQ;IACRC,MAAM;AACR,EAAC;AAED,OAAO,MAAMpC,gBAAgB,CAACJ;IAC5B,OAAOyC,QAAQzC,WAAW0C,KAAK,EAAEC,UAAU3C,WAAW4C,SAAS,EAAED;AACnE,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculateBackoffWaitUntil.d.ts","sourceRoot":"","sources":["../../../src/queues/errors/calculateBackoffWaitUntil.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAI/D,wBAAgB,yBAAyB,CAAC,EACxC,aAAa,EACb,UAAU,GACX,EAAE;IACD,aAAa,EAAE,MAAM,GAAG,WAAW,CAAA;IACnC,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"calculateBackoffWaitUntil.d.ts","sourceRoot":"","sources":["../../../src/queues/errors/calculateBackoffWaitUntil.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAI/D,wBAAgB,yBAAyB,CAAC,EACxC,aAAa,EACb,UAAU,GACX,EAAE;IACD,aAAa,EAAE,MAAM,GAAG,WAAW,CAAA;IACnC,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,IAAI,CAmBP"}
|
|
@@ -1,27 +1,19 @@
|
|
|
1
1
|
import { getCurrentDate } from '../utilities/getCurrentDate.js';
|
|
2
2
|
export function calculateBackoffWaitUntil({ retriesConfig, totalTried }) {
|
|
3
|
-
|
|
3
|
+
const now = getCurrentDate();
|
|
4
|
+
let waitUntil = now;
|
|
4
5
|
if (typeof retriesConfig === 'object') {
|
|
5
6
|
if (retriesConfig.backoff) {
|
|
6
7
|
if (retriesConfig.backoff.type === 'fixed') {
|
|
7
|
-
waitUntil = retriesConfig.backoff.delay ? new Date(
|
|
8
|
+
waitUntil = retriesConfig.backoff.delay ? new Date(now.getTime() + retriesConfig.backoff.delay) : now;
|
|
8
9
|
} else if (retriesConfig.backoff.type === 'exponential') {
|
|
9
10
|
// 2 ^ (attempts - 1) * delay (current attempt is not included in totalTried, thus no need for -1)
|
|
10
11
|
const delay = retriesConfig.backoff.delay ? retriesConfig.backoff.delay : 0;
|
|
11
|
-
waitUntil = new Date(
|
|
12
|
+
waitUntil = new Date(now.getTime() + Math.pow(2, totalTried) * delay);
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
-
const differenceInMSBetweenNowAndWaitUntil = waitUntil.getTime() - getCurrentDate().getTime()
|
|
17
|
-
|
|
18
|
-
const differenceInSBetweenNowAndWaitUntil = differenceInMSBetweenNowAndWaitUntil / 1000
|
|
19
|
-
console.log('Calculated backoff', {
|
|
20
|
-
differenceInMSBetweenNowAndWaitUntil,
|
|
21
|
-
differenceInSBetweenNowAndWaitUntil,
|
|
22
|
-
retriesConfig,
|
|
23
|
-
totalTried,
|
|
24
|
-
})*/ return waitUntil;
|
|
16
|
+
return waitUntil;
|
|
25
17
|
}
|
|
26
18
|
|
|
27
19
|
//# sourceMappingURL=calculateBackoffWaitUntil.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/queues/errors/calculateBackoffWaitUntil.ts"],"sourcesContent":["import type { RetryConfig } from '../config/types/taskTypes.js'\n\nimport { getCurrentDate } from '../utilities/getCurrentDate.js'\n\nexport function calculateBackoffWaitUntil({\n retriesConfig,\n totalTried,\n}: {\n retriesConfig: number | RetryConfig\n totalTried: number\n}): Date {\n let waitUntil: Date =
|
|
1
|
+
{"version":3,"sources":["../../../src/queues/errors/calculateBackoffWaitUntil.ts"],"sourcesContent":["import type { RetryConfig } from '../config/types/taskTypes.js'\n\nimport { getCurrentDate } from '../utilities/getCurrentDate.js'\n\nexport function calculateBackoffWaitUntil({\n retriesConfig,\n totalTried,\n}: {\n retriesConfig: number | RetryConfig\n totalTried: number\n}): Date {\n const now = getCurrentDate()\n let waitUntil: Date = now\n\n if (typeof retriesConfig === 'object') {\n if (retriesConfig.backoff) {\n if (retriesConfig.backoff.type === 'fixed') {\n waitUntil = retriesConfig.backoff.delay\n ? new Date(now.getTime() + retriesConfig.backoff.delay)\n : now\n } else if (retriesConfig.backoff.type === 'exponential') {\n // 2 ^ (attempts - 1) * delay (current attempt is not included in totalTried, thus no need for -1)\n const delay = retriesConfig.backoff.delay ? retriesConfig.backoff.delay : 0\n waitUntil = new Date(now.getTime() + Math.pow(2, totalTried) * delay)\n }\n }\n }\n\n return waitUntil\n}\n"],"names":["getCurrentDate","calculateBackoffWaitUntil","retriesConfig","totalTried","now","waitUntil","backoff","type","delay","Date","getTime","Math","pow"],"mappings":"AAEA,SAASA,cAAc,QAAQ,iCAAgC;AAE/D,OAAO,SAASC,0BAA0B,EACxCC,aAAa,EACbC,UAAU,EAIX;IACC,MAAMC,MAAMJ;IACZ,IAAIK,YAAkBD;IAEtB,IAAI,OAAOF,kBAAkB,UAAU;QACrC,IAAIA,cAAcI,OAAO,EAAE;YACzB,IAAIJ,cAAcI,OAAO,CAACC,IAAI,KAAK,SAAS;gBAC1CF,YAAYH,cAAcI,OAAO,CAACE,KAAK,GACnC,IAAIC,KAAKL,IAAIM,OAAO,KAAKR,cAAcI,OAAO,CAACE,KAAK,IACpDJ;YACN,OAAO,IAAIF,cAAcI,OAAO,CAACC,IAAI,KAAK,eAAe;gBACvD,kGAAkG;gBAClG,MAAMC,QAAQN,cAAcI,OAAO,CAACE,KAAK,GAAGN,cAAcI,OAAO,CAACE,KAAK,GAAG;gBAC1EH,YAAY,IAAII,KAAKL,IAAIM,OAAO,KAAKC,KAAKC,GAAG,CAAC,GAAGT,cAAcK;YACjE;QACF;IACF;IAEA,OAAOH;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleWorkflowError.d.ts","sourceRoot":"","sources":["../../../src/queues/errors/handleWorkflowError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sDAAsD,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAK/C;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,KAAK,EACL,GAAG,EACH,MAAc,EACd,SAAS,GACV,EAAE;IACD,KAAK,EAAE,aAAa,CAAA;IACpB,GAAG,EAAE,cAAc,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,iBAAiB,CAAA;CAC7B,GAAG,OAAO,CAAC;IACV,aAAa,EAAE,OAAO,CAAA;CACvB,CAAC,
|
|
1
|
+
{"version":3,"file":"handleWorkflowError.d.ts","sourceRoot":"","sources":["../../../src/queues/errors/handleWorkflowError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sDAAsD,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAK/C;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,KAAK,EACL,GAAG,EACH,MAAc,EACd,SAAS,GACV,EAAE;IACD,KAAK,EAAE,aAAa,CAAA;IACpB,GAAG,EAAE,cAAc,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,iBAAiB,CAAA;CAC7B,GAAG,OAAO,CAAC;IACV,aAAa,EAAE,OAAO,CAAA;CACvB,CAAC,CA6DD"}
|
|
@@ -15,7 +15,15 @@ import { getWorkflowRetryBehavior } from './getWorkflowRetryBehavior.js';
|
|
|
15
15
|
message: error.message,
|
|
16
16
|
stack: error.stack
|
|
17
17
|
};
|
|
18
|
-
|
|
18
|
+
// No retries configured => permanently fail. Errors reaching this handler are
|
|
19
|
+
// workflow-level (task errors are routed to handleTaskError first), so there's
|
|
20
|
+
// nothing else to bound them.
|
|
21
|
+
const hasNoRetriesConfigured = workflowConfig.retries === undefined || workflowConfig.retries === null;
|
|
22
|
+
const { hasFinalError, maxWorkflowRetries, waitUntil } = hasNoRetriesConfigured ? {
|
|
23
|
+
hasFinalError: true,
|
|
24
|
+
maxWorkflowRetries: undefined,
|
|
25
|
+
waitUntil: undefined
|
|
26
|
+
} : getWorkflowRetryBehavior({
|
|
19
27
|
job,
|
|
20
28
|
retriesConfig: workflowConfig.retries
|
|
21
29
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/queues/errors/handleWorkflowError.ts"],"sourcesContent":["import type { PayloadRequest } from '../../index.js'\nimport type { RunJobsSilent } from '../localAPI.js'\nimport type { UpdateJobFunction } from '../operations/runJobs/runJob/getUpdateJobFunction.js'\nimport type { WorkflowError } from './index.js'\n\nimport { getCurrentDate } from '../utilities/getCurrentDate.js'\nimport { getWorkflowRetryBehavior } from './getWorkflowRetryBehavior.js'\n\n/**\n * This is called if a workflow catches an error. It determines if it's a final error\n * or not and handles logging.\n * A Workflow error = error that happens anywhere in between running tasks.\n *\n * This function assumes that the error is not a TaskError, but a WorkflowError. If a task errors,\n * only a TaskError should be thrown, not a WorkflowError.\n */\nexport async function handleWorkflowError({\n error,\n req,\n silent = false,\n updateJob,\n}: {\n error: WorkflowError\n req: PayloadRequest\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n updateJob: UpdateJobFunction\n}): Promise<{\n hasFinalError: boolean\n}> {\n const { job, workflowConfig } = error.args\n\n const errorJSON = {\n name: error.name,\n cancelled: Boolean('cancelled' in error && error.cancelled),\n message: error.message,\n stack: error.stack,\n }\n\n const { hasFinalError, maxWorkflowRetries, waitUntil } = getWorkflowRetryBehavior({\n
|
|
1
|
+
{"version":3,"sources":["../../../src/queues/errors/handleWorkflowError.ts"],"sourcesContent":["import type { PayloadRequest } from '../../index.js'\nimport type { RunJobsSilent } from '../localAPI.js'\nimport type { UpdateJobFunction } from '../operations/runJobs/runJob/getUpdateJobFunction.js'\nimport type { WorkflowError } from './index.js'\n\nimport { getCurrentDate } from '../utilities/getCurrentDate.js'\nimport { getWorkflowRetryBehavior } from './getWorkflowRetryBehavior.js'\n\n/**\n * This is called if a workflow catches an error. It determines if it's a final error\n * or not and handles logging.\n * A Workflow error = error that happens anywhere in between running tasks.\n *\n * This function assumes that the error is not a TaskError, but a WorkflowError. If a task errors,\n * only a TaskError should be thrown, not a WorkflowError.\n */\nexport async function handleWorkflowError({\n error,\n req,\n silent = false,\n updateJob,\n}: {\n error: WorkflowError\n req: PayloadRequest\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n updateJob: UpdateJobFunction\n}): Promise<{\n hasFinalError: boolean\n}> {\n const { job, workflowConfig } = error.args\n\n const errorJSON = {\n name: error.name,\n cancelled: Boolean('cancelled' in error && error.cancelled),\n message: error.message,\n stack: error.stack,\n }\n\n // No retries configured => permanently fail. Errors reaching this handler are\n // workflow-level (task errors are routed to handleTaskError first), so there's\n // nothing else to bound them.\n const hasNoRetriesConfigured =\n workflowConfig.retries === undefined || workflowConfig.retries === null\n\n const { hasFinalError, maxWorkflowRetries, waitUntil } = hasNoRetriesConfigured\n ? { hasFinalError: true, maxWorkflowRetries: undefined, waitUntil: undefined }\n : getWorkflowRetryBehavior({\n job,\n retriesConfig: workflowConfig.retries,\n })\n\n if (!hasFinalError) {\n if (job.waitUntil) {\n // Check if waitUntil is in the past\n const waitUntil = new Date(job.waitUntil)\n if (waitUntil < getCurrentDate()) {\n // Outdated waitUntil, remove it\n delete job.waitUntil\n }\n }\n\n // Update job's waitUntil only if this waitUntil is later than the current one\n if (waitUntil && (!job.waitUntil || waitUntil > new Date(job.waitUntil))) {\n job.waitUntil = waitUntil.toISOString()\n }\n }\n\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n req.payload.logger.error({\n err: error,\n msg: `Error running job ${jobLabel} id: ${job.id} attempt ${job.totalTried + 1}${maxWorkflowRetries !== undefined ? '/' + (maxWorkflowRetries + 1) : ''}`,\n })\n }\n\n // Tasks update the job if they error - but in case there is an unhandled error (e.g. in the workflow itself, not in a task)\n // we need to ensure the job is updated to reflect the error\n await updateJob({\n error: errorJSON,\n hasError: hasFinalError, // If reached max retries => final error. If hasError is true this job will not be retried\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n waitUntil: job.waitUntil,\n })\n\n return {\n hasFinalError,\n }\n}\n"],"names":["getCurrentDate","getWorkflowRetryBehavior","handleWorkflowError","error","req","silent","updateJob","job","workflowConfig","args","errorJSON","name","cancelled","Boolean","message","stack","hasNoRetriesConfigured","retries","undefined","hasFinalError","maxWorkflowRetries","waitUntil","retriesConfig","Date","toISOString","jobLabel","workflowSlug","taskSlug","payload","logger","err","msg","id","totalTried","hasError","processing"],"mappings":"AAKA,SAASA,cAAc,QAAQ,iCAAgC;AAC/D,SAASC,wBAAwB,QAAQ,gCAA+B;AAExE;;;;;;;CAOC,GACD,OAAO,eAAeC,oBAAoB,EACxCC,KAAK,EACLC,GAAG,EACHC,SAAS,KAAK,EACdC,SAAS,EAcV;IAGC,MAAM,EAAEC,GAAG,EAAEC,cAAc,EAAE,GAAGL,MAAMM,IAAI;IAE1C,MAAMC,YAAY;QAChBC,MAAMR,MAAMQ,IAAI;QAChBC,WAAWC,QAAQ,eAAeV,SAASA,MAAMS,SAAS;QAC1DE,SAASX,MAAMW,OAAO;QACtBC,OAAOZ,MAAMY,KAAK;IACpB;IAEA,8EAA8E;IAC9E,+EAA+E;IAC/E,8BAA8B;IAC9B,MAAMC,yBACJR,eAAeS,OAAO,KAAKC,aAAaV,eAAeS,OAAO,KAAK;IAErE,MAAM,EAAEE,aAAa,EAAEC,kBAAkB,EAAEC,SAAS,EAAE,GAAGL,yBACrD;QAAEG,eAAe;QAAMC,oBAAoBF;QAAWG,WAAWH;IAAU,IAC3EjB,yBAAyB;QACvBM;QACAe,eAAed,eAAeS,OAAO;IACvC;IAEJ,IAAI,CAACE,eAAe;QAClB,IAAIZ,IAAIc,SAAS,EAAE;YACjB,oCAAoC;YACpC,MAAMA,YAAY,IAAIE,KAAKhB,IAAIc,SAAS;YACxC,IAAIA,YAAYrB,kBAAkB;gBAChC,gCAAgC;gBAChC,OAAOO,IAAIc,SAAS;YACtB;QACF;QAEA,8EAA8E;QAC9E,IAAIA,aAAc,CAAA,CAACd,IAAIc,SAAS,IAAIA,YAAY,IAAIE,KAAKhB,IAAIc,SAAS,CAAA,GAAI;YACxEd,IAAIc,SAAS,GAAGA,UAAUG,WAAW;QACvC;IACF;IAEA,MAAMC,WAAWlB,IAAImB,YAAY,IAAI,CAAC,MAAM,EAAEnB,IAAIoB,QAAQ,EAAE;IAE5D,IAAI,CAACtB,UAAW,OAAOA,WAAW,YAAY,CAACA,OAAOF,KAAK,EAAG;QAC5DC,IAAIwB,OAAO,CAACC,MAAM,CAAC1B,KAAK,CAAC;YACvB2B,KAAK3B;YACL4B,KAAK,CAAC,kBAAkB,EAAEN,SAAS,KAAK,EAAElB,IAAIyB,EAAE,CAAC,SAAS,EAAEzB,IAAI0B,UAAU,GAAG,IAAIb,uBAAuBF,YAAY,MAAOE,CAAAA,qBAAqB,CAAA,IAAK,IAAI;QAC3J;IACF;IAEA,4HAA4H;IAC5H,4DAA4D;IAC5D,MAAMd,UAAU;QACdH,OAAOO;QACPwB,UAAUf;QACVgB,YAAY;QACZF,YAAY,AAAC1B,CAAAA,IAAI0B,UAAU,IAAI,CAAA,IAAK;QACpCZ,WAAWd,IAAIc,SAAS;IAC1B;IAEA,OAAO;QACLF;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"countRunnableOrActiveJobsForQueue.d.ts","sourceRoot":"","sources":["../../../../src/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,yBAAyB,CAAA;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;
|
|
1
|
+
{"version":3,"file":"countRunnableOrActiveJobsForQueue.d.ts","sourceRoot":"","sources":["../../../../src/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,yBAAyB,CAAA;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AAIxE;;;;;GAKG;AACH,wBAAsB,iCAAiC,CAAC,EACtD,aAAqB,EACrB,KAAK,EACL,GAAG,EACH,QAAQ,EACR,YAAY,GACb,EAAE;IACD;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,cAAc,CAAA;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,YAAY,CAAC,EAAE,aAAa,CAAA;CAC7B,GAAG,OAAO,CAAC,MAAM,CAAC,CA8ClB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jobsCollectionSlug } from '../../config/collection.js';
|
|
1
2
|
/**
|
|
2
3
|
* Gets all queued jobs that can be run. This means they either:
|
|
3
4
|
* - failed but do not have a definitive error => can be retried
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
45
|
const runnableOrActiveJobsForQueue = await req.payload.db.count({
|
|
45
|
-
collection:
|
|
46
|
+
collection: jobsCollectionSlug,
|
|
46
47
|
req,
|
|
47
48
|
where: {
|
|
48
49
|
and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.ts"],"sourcesContent":["import type { PayloadRequest, Where } from '../../../types/index.js'\nimport type { TaskType } from '../../config/types/taskTypes.js'\nimport type { WorkflowTypes } from '../../config/types/workflowTypes.js'\n\n/**\n * Gets all queued jobs that can be run. This means they either:\n * - failed but do not have a definitive error => can be retried\n * - are currently processing\n * - have not been started yet\n */\nexport async function countRunnableOrActiveJobsForQueue({\n onlyScheduled = false,\n queue,\n req,\n taskSlug,\n workflowSlug,\n}: {\n /**\n * If true, this counts only jobs that have been created through the scheduling system.\n *\n * @default false\n */\n onlyScheduled?: boolean\n queue: string\n req: PayloadRequest\n taskSlug?: TaskType\n workflowSlug?: WorkflowTypes\n}): Promise<number> {\n const and: Where[] = [\n {\n queue: {\n equals: queue,\n },\n },\n\n {\n completedAt: { exists: false },\n },\n {\n error: { exists: false },\n },\n ]\n\n if (taskSlug) {\n and.push({\n taskSlug: {\n equals: taskSlug,\n },\n })\n } else if (workflowSlug) {\n and.push({\n workflowSlug: {\n equals: workflowSlug,\n },\n })\n }\n if (onlyScheduled) {\n and.push({\n 'meta.scheduled': {\n equals: true,\n },\n })\n }\n\n const runnableOrActiveJobsForQueue = await req.payload.db.count({\n collection:
|
|
1
|
+
{"version":3,"sources":["../../../../src/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.ts"],"sourcesContent":["import type { PayloadRequest, Where } from '../../../types/index.js'\nimport type { TaskType } from '../../config/types/taskTypes.js'\nimport type { WorkflowTypes } from '../../config/types/workflowTypes.js'\n\nimport { jobsCollectionSlug } from '../../config/collection.js'\n\n/**\n * Gets all queued jobs that can be run. This means they either:\n * - failed but do not have a definitive error => can be retried\n * - are currently processing\n * - have not been started yet\n */\nexport async function countRunnableOrActiveJobsForQueue({\n onlyScheduled = false,\n queue,\n req,\n taskSlug,\n workflowSlug,\n}: {\n /**\n * If true, this counts only jobs that have been created through the scheduling system.\n *\n * @default false\n */\n onlyScheduled?: boolean\n queue: string\n req: PayloadRequest\n taskSlug?: TaskType\n workflowSlug?: WorkflowTypes\n}): Promise<number> {\n const and: Where[] = [\n {\n queue: {\n equals: queue,\n },\n },\n\n {\n completedAt: { exists: false },\n },\n {\n error: { exists: false },\n },\n ]\n\n if (taskSlug) {\n and.push({\n taskSlug: {\n equals: taskSlug,\n },\n })\n } else if (workflowSlug) {\n and.push({\n workflowSlug: {\n equals: workflowSlug,\n },\n })\n }\n if (onlyScheduled) {\n and.push({\n 'meta.scheduled': {\n equals: true,\n },\n })\n }\n\n const runnableOrActiveJobsForQueue = await req.payload.db.count({\n collection: jobsCollectionSlug,\n req,\n where: {\n and,\n },\n })\n\n return runnableOrActiveJobsForQueue.totalDocs\n}\n"],"names":["jobsCollectionSlug","countRunnableOrActiveJobsForQueue","onlyScheduled","queue","req","taskSlug","workflowSlug","and","equals","completedAt","exists","error","push","runnableOrActiveJobsForQueue","payload","db","count","collection","where","totalDocs"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,6BAA4B;AAE/D;;;;;CAKC,GACD,OAAO,eAAeC,kCAAkC,EACtDC,gBAAgB,KAAK,EACrBC,KAAK,EACLC,GAAG,EACHC,QAAQ,EACRC,YAAY,EAYb;IACC,MAAMC,MAAe;QACnB;YACEJ,OAAO;gBACLK,QAAQL;YACV;QACF;QAEA;YACEM,aAAa;gBAAEC,QAAQ;YAAM;QAC/B;QACA;YACEC,OAAO;gBAAED,QAAQ;YAAM;QACzB;KACD;IAED,IAAIL,UAAU;QACZE,IAAIK,IAAI,CAAC;YACPP,UAAU;gBACRG,QAAQH;YACV;QACF;IACF,OAAO,IAAIC,cAAc;QACvBC,IAAIK,IAAI,CAAC;YACPN,cAAc;gBACZE,QAAQF;YACV;QACF;IACF;IACA,IAAIJ,eAAe;QACjBK,IAAIK,IAAI,CAAC;YACP,kBAAkB;gBAChBJ,QAAQ;YACV;QACF;IACF;IAEA,MAAMK,+BAA+B,MAAMT,IAAIU,OAAO,CAACC,EAAE,CAACC,KAAK,CAAC;QAC9DC,YAAYjB;QACZI;QACAc,OAAO;YACLX;QACF;IACF;IAEA,OAAOM,6BAA6BM,SAAS;AAC/C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/queues/operations/handleSchedules/defaultAfterSchedule.ts"],"sourcesContent":["import type { AfterScheduleFn } from '../../config/types/index.js'\n\nimport { type JobStats, jobStatsGlobalSlug } from '../../config/global.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\n\ntype JobStatsScheduledRuns = NonNullable<\n NonNullable<NonNullable<JobStats['stats']>['scheduledRuns']>['queues']\n>[string]\n\nexport const defaultAfterSchedule: AfterScheduleFn = async ({ jobStats, queueable, req }) => {\n const existingQueuesConfig =\n jobStats?.stats?.scheduledRuns?.queues?.[queueable.scheduleConfig.queue] || {}\n\n const queueConfig: JobStatsScheduledRuns = {\n ...existingQueuesConfig,\n }\n if (queueable.taskConfig) {\n ;(queueConfig.tasks ??= {})[queueable.taskConfig.slug] = {\n lastScheduledRun: getCurrentDate().toISOString(),\n }\n } else if (queueable.workflowConfig) {\n ;(queueConfig.workflows ??= {})[queueable.workflowConfig.slug] = {\n lastScheduledRun: getCurrentDate().toISOString(),\n }\n }\n\n // Add to payload-jobs-stats global regardless of the status\n if (jobStats) {\n await req.payload.db.updateGlobal({\n slug: jobStatsGlobalSlug,\n data: {\n ...(jobStats || {}),\n stats: {\n ...(jobStats?.stats || {}),\n scheduledRuns: {\n ...(jobStats?.stats?.scheduledRuns || {}),\n queues: {\n ...(jobStats?.stats?.scheduledRuns?.queues || {}),\n [queueable.scheduleConfig.queue]: queueConfig,\n },\n },\n },\n updatedAt:
|
|
1
|
+
{"version":3,"sources":["../../../../src/queues/operations/handleSchedules/defaultAfterSchedule.ts"],"sourcesContent":["import type { AfterScheduleFn } from '../../config/types/index.js'\n\nimport { type JobStats, jobStatsGlobalSlug } from '../../config/global.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\n\ntype JobStatsScheduledRuns = NonNullable<\n NonNullable<NonNullable<JobStats['stats']>['scheduledRuns']>['queues']\n>[string]\n\nexport const defaultAfterSchedule: AfterScheduleFn = async ({ jobStats, queueable, req }) => {\n const existingQueuesConfig =\n jobStats?.stats?.scheduledRuns?.queues?.[queueable.scheduleConfig.queue] || {}\n\n const queueConfig: JobStatsScheduledRuns = {\n ...existingQueuesConfig,\n }\n if (queueable.taskConfig) {\n ;(queueConfig.tasks ??= {})[queueable.taskConfig.slug] = {\n lastScheduledRun: getCurrentDate().toISOString(),\n }\n } else if (queueable.workflowConfig) {\n ;(queueConfig.workflows ??= {})[queueable.workflowConfig.slug] = {\n lastScheduledRun: getCurrentDate().toISOString(),\n }\n }\n\n // Add to payload-jobs-stats global regardless of the status\n if (jobStats) {\n await req.payload.db.updateGlobal({\n slug: jobStatsGlobalSlug,\n data: {\n ...(jobStats || {}),\n stats: {\n ...(jobStats?.stats || {}),\n scheduledRuns: {\n ...(jobStats?.stats?.scheduledRuns || {}),\n queues: {\n ...(jobStats?.stats?.scheduledRuns?.queues || {}),\n [queueable.scheduleConfig.queue]: queueConfig,\n },\n },\n },\n updatedAt: getCurrentDate().toISOString(),\n } as JobStats,\n req,\n returning: false,\n })\n } else {\n await req.payload.db.createGlobal({\n slug: jobStatsGlobalSlug,\n data: {\n createdAt: getCurrentDate().toISOString(),\n stats: {\n scheduledRuns: {\n queues: {\n [queueable.scheduleConfig.queue]: queueConfig,\n },\n },\n },\n } as JobStats,\n req,\n returning: false,\n })\n }\n}\n"],"names":["jobStatsGlobalSlug","getCurrentDate","defaultAfterSchedule","jobStats","queueable","req","existingQueuesConfig","stats","scheduledRuns","queues","scheduleConfig","queue","queueConfig","taskConfig","tasks","slug","lastScheduledRun","toISOString","workflowConfig","workflows","payload","db","updateGlobal","data","updatedAt","returning","createGlobal","createdAt"],"mappings":"AAEA,SAAwBA,kBAAkB,QAAQ,yBAAwB;AAC1E,SAASC,cAAc,QAAQ,oCAAmC;AAMlE,OAAO,MAAMC,uBAAwC,OAAO,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,GAAG,EAAE;IACtF,MAAMC,uBACJH,UAAUI,OAAOC,eAAeC,QAAQ,CAACL,UAAUM,cAAc,CAACC,KAAK,CAAC,IAAI,CAAC;IAE/E,MAAMC,cAAqC;QACzC,GAAGN,oBAAoB;IACzB;IACA,IAAIF,UAAUS,UAAU,EAAE;;QACtBD,CAAAA,YAAYE,KAAK,KAAK,CAAC,CAAA,CAAE,CAACV,UAAUS,UAAU,CAACE,IAAI,CAAC,GAAG;YACvDC,kBAAkBf,iBAAiBgB,WAAW;QAChD;IACF,OAAO,IAAIb,UAAUc,cAAc,EAAE;;QACjCN,CAAAA,YAAYO,SAAS,KAAK,CAAC,CAAA,CAAE,CAACf,UAAUc,cAAc,CAACH,IAAI,CAAC,GAAG;YAC/DC,kBAAkBf,iBAAiBgB,WAAW;QAChD;IACF;IAEA,4DAA4D;IAC5D,IAAId,UAAU;QACZ,MAAME,IAAIe,OAAO,CAACC,EAAE,CAACC,YAAY,CAAC;YAChCP,MAAMf;YACNuB,MAAM;gBACJ,GAAIpB,YAAY,CAAC,CAAC;gBAClBI,OAAO;oBACL,GAAIJ,UAAUI,SAAS,CAAC,CAAC;oBACzBC,eAAe;wBACb,GAAIL,UAAUI,OAAOC,iBAAiB,CAAC,CAAC;wBACxCC,QAAQ;4BACN,GAAIN,UAAUI,OAAOC,eAAeC,UAAU,CAAC,CAAC;4BAChD,CAACL,UAAUM,cAAc,CAACC,KAAK,CAAC,EAAEC;wBACpC;oBACF;gBACF;gBACAY,WAAWvB,iBAAiBgB,WAAW;YACzC;YACAZ;YACAoB,WAAW;QACb;IACF,OAAO;QACL,MAAMpB,IAAIe,OAAO,CAACC,EAAE,CAACK,YAAY,CAAC;YAChCX,MAAMf;YACNuB,MAAM;gBACJI,WAAW1B,iBAAiBgB,WAAW;gBACvCV,OAAO;oBACLC,eAAe;wBACbC,QAAQ;4BACN,CAACL,UAAUM,cAAc,CAACC,KAAK,CAAC,EAAEC;wBACpC;oBACF;gBACF;YACF;YACAP;YACAoB,WAAW;QACb;IACF;AACF,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/queues/operations/handleSchedules/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAoB,SAAS,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE9F,OAAO,EAAE,KAAK,QAAQ,EAAsB,MAAM,wBAAwB,CAAA;AAK1E,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB,CAAA;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,EACpC,SAAiB,EACjB,KAAK,EAAE,MAAM,EACb,GAAG,GACJ,EAAE;IACD;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;CACpB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA+EjC;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,KAAK,EACL,cAAc,EACd,KAAK,EACL,UAAU,EACV,cAAc,GACf,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,EAAE,QAAQ,CAAA;IACf,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC,GAAG,KAAK,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/queues/operations/handleSchedules/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAoB,SAAS,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE9F,OAAO,EAAE,KAAK,QAAQ,EAAsB,MAAM,wBAAwB,CAAA;AAK1E,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB,CAAA;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,EACpC,SAAiB,EACjB,KAAK,EAAE,MAAM,EACb,GAAG,GACJ,EAAE;IACD;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;CACpB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA+EjC;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,KAAK,EACL,cAAc,EACd,KAAK,EACL,UAAU,EACV,cAAc,GACf,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,EAAE,QAAQ,CAAA;IACf,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC,GAAG,KAAK,GAAG,SAAS,CAqBpB;AAED,wBAAsB,iBAAiB,CAAC,EACtC,SAAS,EACT,GAAG,EACH,KAAK,GACN,EAAE;IACD,SAAS,EAAE,SAAS,CAAA;IACpB,GAAG,EAAE,cAAc,CAAA;IACnB,KAAK,EAAE,QAAQ,CAAA;CAChB,GAAG,OAAO,CAAC;IACV,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;IAChB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAA;CACxC,CAAC,CAyED"}
|
|
@@ -82,7 +82,10 @@ import { getQueuesWithSchedules } from './getQueuesWithSchedules.js';
|
|
|
82
82
|
export function checkQueueableTimeConstraints({ queue, scheduleConfig, stats, taskConfig, workflowConfig }) {
|
|
83
83
|
const queueScheduleStats = stats?.stats?.scheduledRuns?.queues?.[queue];
|
|
84
84
|
const lastScheduledRun = taskConfig ? queueScheduleStats?.tasks?.[taskConfig.slug]?.lastScheduledRun : queueScheduleStats?.workflows?.[workflowConfig?.slug ?? '']?.lastScheduledRun;
|
|
85
|
-
const nextRun = new Cron(scheduleConfig.cron
|
|
85
|
+
const nextRun = new Cron(scheduleConfig.cron, {
|
|
86
|
+
// TODO: Remove this compatibility option in 4.0. This only exists to ensure backwards-compatibility between Croner v9 and Croner v10 cron syntax
|
|
87
|
+
sloppyRanges: true
|
|
88
|
+
}).nextRun(lastScheduledRun ?? undefined);
|
|
86
89
|
if (!nextRun) {
|
|
87
90
|
return false;
|
|
88
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/queues/operations/handleSchedules/index.ts"],"sourcesContent":["import { Cron } from 'croner'\n\nimport type { Job, TaskConfig, WorkflowConfig } from '../../../index.js'\nimport type { PayloadRequest } from '../../../types/index.js'\nimport type { BeforeScheduleFn, Queueable, ScheduleConfig } from '../../config/types/index.js'\n\nimport { type JobStats, jobStatsGlobalSlug } from '../../config/global.js'\nimport { defaultAfterSchedule } from './defaultAfterSchedule.js'\nimport { defaultBeforeSchedule } from './defaultBeforeSchedule.js'\nimport { getQueuesWithSchedules } from './getQueuesWithSchedules.js'\n\nexport type HandleSchedulesResult = {\n errored: Queueable[]\n queued: Queueable[]\n skipped: Queueable[]\n}\n\n/**\n * On vercel, we cannot auto-schedule jobs using a Cron - instead, we'll use this same endpoint that can\n * also be called from Vercel Cron for auto-running jobs.\n *\n * The benefit of doing it like this instead of a separate endpoint is that we can run jobs immediately\n * after they are scheduled\n */\nexport async function handleSchedules({\n allQueues = false,\n queue: _queue,\n req,\n}: {\n /**\n * If you want to schedule jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * If you want to only schedule jobs that are set to schedule in a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n}): Promise<HandleSchedulesResult> {\n const queue = _queue ?? 'default'\n const jobsConfig = req.payload.config.jobs\n const queuesWithSchedules = getQueuesWithSchedules({\n jobsConfig,\n })\n\n if (Object.keys(queuesWithSchedules).length === 0) {\n // No schedules defined => return early, before fetching jobsStatsGlobal, as the global may not even exist\n return {\n errored: [],\n queued: [],\n skipped: [],\n }\n }\n\n const stats: JobStats = await req.payload.db.findGlobal({\n slug: jobStatsGlobalSlug,\n req,\n })\n\n /**\n * Almost last step! Tasks and Workflows added here just need to be constraint-checked (e.g max. 1 running task etc.),\n * before we can queue them\n */\n const queueables: Queueable[] = []\n\n // Need to know when that particular job was last scheduled in that particular queue\n\n for (const [queueName, { schedules }] of Object.entries(queuesWithSchedules)) {\n if (!allQueues && queueName !== queue) {\n // If a queue is specified, only schedule jobs for that queue\n continue\n }\n for (const schedulable of schedules) {\n const queuable = checkQueueableTimeConstraints({\n queue: queueName,\n scheduleConfig: schedulable.scheduleConfig,\n stats,\n taskConfig: schedulable.taskConfig,\n workflowConfig: schedulable.workflowConfig,\n })\n if (queuable) {\n queueables.push(queuable)\n }\n }\n }\n\n const queued: Queueable[] = []\n const skipped: Queueable[] = []\n const errored: Queueable[] = []\n\n /**\n * Now queue, but check for constraints (= beforeSchedule) first.\n * Default constraint (= defaultBeforeSchedule): max. 1 running / scheduled task or workflow per queue\n */\n for (const queueable of queueables) {\n const { status } = await scheduleQueueable({\n queueable,\n req,\n stats,\n })\n switch (status) {\n case 'error':\n errored.push(queueable)\n break\n case 'skipped':\n skipped.push(queueable)\n break\n case 'success':\n queued.push(queueable)\n break\n }\n }\n return {\n errored,\n queued,\n skipped,\n }\n}\n\nexport function checkQueueableTimeConstraints({\n queue,\n scheduleConfig,\n stats,\n taskConfig,\n workflowConfig,\n}: {\n queue: string\n scheduleConfig: ScheduleConfig\n stats: JobStats\n taskConfig?: TaskConfig\n workflowConfig?: WorkflowConfig\n}): false | Queueable {\n const queueScheduleStats = stats?.stats?.scheduledRuns?.queues?.[queue]\n\n const lastScheduledRun = taskConfig\n ? queueScheduleStats?.tasks?.[taskConfig.slug]?.lastScheduledRun\n : queueScheduleStats?.workflows?.[workflowConfig?.slug ?? '']?.lastScheduledRun\n\n const nextRun = new Cron(scheduleConfig.cron).nextRun(lastScheduledRun ?? undefined)\n\n if (!nextRun) {\n return false\n }\n return {\n scheduleConfig,\n taskConfig,\n waitUntil: nextRun,\n workflowConfig,\n }\n}\n\nexport async function scheduleQueueable({\n queueable,\n req,\n stats,\n}: {\n queueable: Queueable\n req: PayloadRequest\n stats: JobStats\n}): Promise<{\n job?: Job<false>\n status: 'error' | 'skipped' | 'success'\n}> {\n if (!queueable.taskConfig && !queueable.workflowConfig) {\n return {\n status: 'error',\n }\n }\n\n const beforeScheduleFn = queueable.scheduleConfig.hooks?.beforeSchedule\n const afterScheduleFN = queueable.scheduleConfig.hooks?.afterSchedule\n\n try {\n const beforeScheduleResult: Awaited<ReturnType<BeforeScheduleFn>> = await (\n beforeScheduleFn ?? defaultBeforeSchedule\n )({\n // @ts-expect-error we know defaultBeforeSchedule will never call itself => pass null\n defaultBeforeSchedule: beforeScheduleFn ? defaultBeforeSchedule : null,\n jobStats: stats,\n queueable,\n req,\n })\n\n if (!beforeScheduleResult.shouldSchedule) {\n await (afterScheduleFN ?? defaultAfterSchedule)({\n // @ts-expect-error we know defaultAfterchedule will never call itself => pass null\n defaultAfterSchedule: afterScheduleFN ? defaultAfterSchedule : null,\n jobStats: stats,\n queueable,\n req,\n status: 'skipped',\n })\n return {\n status: 'skipped',\n }\n }\n\n const job = (await req.payload.jobs.queue({\n input: beforeScheduleResult.input ?? {},\n meta: {\n scheduled: true,\n },\n queue: queueable.scheduleConfig.queue,\n req,\n task: queueable?.taskConfig?.slug,\n waitUntil: beforeScheduleResult.waitUntil,\n workflow: queueable.workflowConfig?.slug,\n } as Parameters<typeof req.payload.jobs.queue>[0])) as unknown as Job<false>\n\n await (afterScheduleFN ?? defaultAfterSchedule)({\n // @ts-expect-error we know defaultAfterchedule will never call itself => pass null\n defaultAfterSchedule: afterScheduleFN ? defaultAfterSchedule : null,\n job,\n jobStats: stats,\n queueable,\n req,\n status: 'success',\n })\n return {\n status: 'success',\n }\n } catch (error) {\n await (afterScheduleFN ?? defaultAfterSchedule)({\n // @ts-expect-error we know defaultAfterchedule will never call itself => pass null\n defaultAfterSchedule: afterScheduleFN ? defaultAfterSchedule : null,\n error: error as Error,\n jobStats: stats,\n queueable,\n req,\n status: 'error',\n })\n return {\n status: 'error',\n }\n }\n}\n"],"names":["Cron","jobStatsGlobalSlug","defaultAfterSchedule","defaultBeforeSchedule","getQueuesWithSchedules","handleSchedules","allQueues","queue","_queue","req","jobsConfig","payload","config","jobs","queuesWithSchedules","Object","keys","length","errored","queued","skipped","stats","db","findGlobal","slug","queueables","queueName","schedules","entries","schedulable","queuable","checkQueueableTimeConstraints","scheduleConfig","taskConfig","workflowConfig","push","queueable","status","scheduleQueueable","queueScheduleStats","scheduledRuns","queues","lastScheduledRun","tasks","workflows","nextRun","cron","undefined","waitUntil","beforeScheduleFn","hooks","beforeSchedule","afterScheduleFN","afterSchedule","beforeScheduleResult","jobStats","shouldSchedule","job","input","meta","scheduled","task","workflow","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/queues/operations/handleSchedules/index.ts"],"sourcesContent":["import { Cron } from 'croner'\n\nimport type { Job, TaskConfig, WorkflowConfig } from '../../../index.js'\nimport type { PayloadRequest } from '../../../types/index.js'\nimport type { BeforeScheduleFn, Queueable, ScheduleConfig } from '../../config/types/index.js'\n\nimport { type JobStats, jobStatsGlobalSlug } from '../../config/global.js'\nimport { defaultAfterSchedule } from './defaultAfterSchedule.js'\nimport { defaultBeforeSchedule } from './defaultBeforeSchedule.js'\nimport { getQueuesWithSchedules } from './getQueuesWithSchedules.js'\n\nexport type HandleSchedulesResult = {\n errored: Queueable[]\n queued: Queueable[]\n skipped: Queueable[]\n}\n\n/**\n * On vercel, we cannot auto-schedule jobs using a Cron - instead, we'll use this same endpoint that can\n * also be called from Vercel Cron for auto-running jobs.\n *\n * The benefit of doing it like this instead of a separate endpoint is that we can run jobs immediately\n * after they are scheduled\n */\nexport async function handleSchedules({\n allQueues = false,\n queue: _queue,\n req,\n}: {\n /**\n * If you want to schedule jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * If you want to only schedule jobs that are set to schedule in a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n}): Promise<HandleSchedulesResult> {\n const queue = _queue ?? 'default'\n const jobsConfig = req.payload.config.jobs\n const queuesWithSchedules = getQueuesWithSchedules({\n jobsConfig,\n })\n\n if (Object.keys(queuesWithSchedules).length === 0) {\n // No schedules defined => return early, before fetching jobsStatsGlobal, as the global may not even exist\n return {\n errored: [],\n queued: [],\n skipped: [],\n }\n }\n\n const stats: JobStats = await req.payload.db.findGlobal({\n slug: jobStatsGlobalSlug,\n req,\n })\n\n /**\n * Almost last step! Tasks and Workflows added here just need to be constraint-checked (e.g max. 1 running task etc.),\n * before we can queue them\n */\n const queueables: Queueable[] = []\n\n // Need to know when that particular job was last scheduled in that particular queue\n\n for (const [queueName, { schedules }] of Object.entries(queuesWithSchedules)) {\n if (!allQueues && queueName !== queue) {\n // If a queue is specified, only schedule jobs for that queue\n continue\n }\n for (const schedulable of schedules) {\n const queuable = checkQueueableTimeConstraints({\n queue: queueName,\n scheduleConfig: schedulable.scheduleConfig,\n stats,\n taskConfig: schedulable.taskConfig,\n workflowConfig: schedulable.workflowConfig,\n })\n if (queuable) {\n queueables.push(queuable)\n }\n }\n }\n\n const queued: Queueable[] = []\n const skipped: Queueable[] = []\n const errored: Queueable[] = []\n\n /**\n * Now queue, but check for constraints (= beforeSchedule) first.\n * Default constraint (= defaultBeforeSchedule): max. 1 running / scheduled task or workflow per queue\n */\n for (const queueable of queueables) {\n const { status } = await scheduleQueueable({\n queueable,\n req,\n stats,\n })\n switch (status) {\n case 'error':\n errored.push(queueable)\n break\n case 'skipped':\n skipped.push(queueable)\n break\n case 'success':\n queued.push(queueable)\n break\n }\n }\n return {\n errored,\n queued,\n skipped,\n }\n}\n\nexport function checkQueueableTimeConstraints({\n queue,\n scheduleConfig,\n stats,\n taskConfig,\n workflowConfig,\n}: {\n queue: string\n scheduleConfig: ScheduleConfig\n stats: JobStats\n taskConfig?: TaskConfig\n workflowConfig?: WorkflowConfig\n}): false | Queueable {\n const queueScheduleStats = stats?.stats?.scheduledRuns?.queues?.[queue]\n\n const lastScheduledRun = taskConfig\n ? queueScheduleStats?.tasks?.[taskConfig.slug]?.lastScheduledRun\n : queueScheduleStats?.workflows?.[workflowConfig?.slug ?? '']?.lastScheduledRun\n\n const nextRun = new Cron(scheduleConfig.cron, {\n // TODO: Remove this compatibility option in 4.0. This only exists to ensure backwards-compatibility between Croner v9 and Croner v10 cron syntax\n sloppyRanges: true,\n }).nextRun(lastScheduledRun ?? undefined)\n\n if (!nextRun) {\n return false\n }\n return {\n scheduleConfig,\n taskConfig,\n waitUntil: nextRun,\n workflowConfig,\n }\n}\n\nexport async function scheduleQueueable({\n queueable,\n req,\n stats,\n}: {\n queueable: Queueable\n req: PayloadRequest\n stats: JobStats\n}): Promise<{\n job?: Job<false>\n status: 'error' | 'skipped' | 'success'\n}> {\n if (!queueable.taskConfig && !queueable.workflowConfig) {\n return {\n status: 'error',\n }\n }\n\n const beforeScheduleFn = queueable.scheduleConfig.hooks?.beforeSchedule\n const afterScheduleFN = queueable.scheduleConfig.hooks?.afterSchedule\n\n try {\n const beforeScheduleResult: Awaited<ReturnType<BeforeScheduleFn>> = await (\n beforeScheduleFn ?? defaultBeforeSchedule\n )({\n // @ts-expect-error we know defaultBeforeSchedule will never call itself => pass null\n defaultBeforeSchedule: beforeScheduleFn ? defaultBeforeSchedule : null,\n jobStats: stats,\n queueable,\n req,\n })\n\n if (!beforeScheduleResult.shouldSchedule) {\n await (afterScheduleFN ?? defaultAfterSchedule)({\n // @ts-expect-error we know defaultAfterchedule will never call itself => pass null\n defaultAfterSchedule: afterScheduleFN ? defaultAfterSchedule : null,\n jobStats: stats,\n queueable,\n req,\n status: 'skipped',\n })\n return {\n status: 'skipped',\n }\n }\n\n const job = (await req.payload.jobs.queue({\n input: beforeScheduleResult.input ?? {},\n meta: {\n scheduled: true,\n },\n queue: queueable.scheduleConfig.queue,\n req,\n task: queueable?.taskConfig?.slug,\n waitUntil: beforeScheduleResult.waitUntil,\n workflow: queueable.workflowConfig?.slug,\n } as Parameters<typeof req.payload.jobs.queue>[0])) as unknown as Job<false>\n\n await (afterScheduleFN ?? defaultAfterSchedule)({\n // @ts-expect-error we know defaultAfterchedule will never call itself => pass null\n defaultAfterSchedule: afterScheduleFN ? defaultAfterSchedule : null,\n job,\n jobStats: stats,\n queueable,\n req,\n status: 'success',\n })\n return {\n status: 'success',\n }\n } catch (error) {\n await (afterScheduleFN ?? defaultAfterSchedule)({\n // @ts-expect-error we know defaultAfterchedule will never call itself => pass null\n defaultAfterSchedule: afterScheduleFN ? defaultAfterSchedule : null,\n error: error as Error,\n jobStats: stats,\n queueable,\n req,\n status: 'error',\n })\n return {\n status: 'error',\n }\n }\n}\n"],"names":["Cron","jobStatsGlobalSlug","defaultAfterSchedule","defaultBeforeSchedule","getQueuesWithSchedules","handleSchedules","allQueues","queue","_queue","req","jobsConfig","payload","config","jobs","queuesWithSchedules","Object","keys","length","errored","queued","skipped","stats","db","findGlobal","slug","queueables","queueName","schedules","entries","schedulable","queuable","checkQueueableTimeConstraints","scheduleConfig","taskConfig","workflowConfig","push","queueable","status","scheduleQueueable","queueScheduleStats","scheduledRuns","queues","lastScheduledRun","tasks","workflows","nextRun","cron","sloppyRanges","undefined","waitUntil","beforeScheduleFn","hooks","beforeSchedule","afterScheduleFN","afterSchedule","beforeScheduleResult","jobStats","shouldSchedule","job","input","meta","scheduled","task","workflow","error"],"mappings":"AAAA,SAASA,IAAI,QAAQ,SAAQ;AAM7B,SAAwBC,kBAAkB,QAAQ,yBAAwB;AAC1E,SAASC,oBAAoB,QAAQ,4BAA2B;AAChE,SAASC,qBAAqB,QAAQ,6BAA4B;AAClE,SAASC,sBAAsB,QAAQ,8BAA6B;AAQpE;;;;;;CAMC,GACD,OAAO,eAAeC,gBAAgB,EACpCC,YAAY,KAAK,EACjBC,OAAOC,MAAM,EACbC,GAAG,EAgBJ;IACC,MAAMF,QAAQC,UAAU;IACxB,MAAME,aAAaD,IAAIE,OAAO,CAACC,MAAM,CAACC,IAAI;IAC1C,MAAMC,sBAAsBV,uBAAuB;QACjDM;IACF;IAEA,IAAIK,OAAOC,IAAI,CAACF,qBAAqBG,MAAM,KAAK,GAAG;QACjD,0GAA0G;QAC1G,OAAO;YACLC,SAAS,EAAE;YACXC,QAAQ,EAAE;YACVC,SAAS,EAAE;QACb;IACF;IAEA,MAAMC,QAAkB,MAAMZ,IAAIE,OAAO,CAACW,EAAE,CAACC,UAAU,CAAC;QACtDC,MAAMvB;QACNQ;IACF;IAEA;;;GAGC,GACD,MAAMgB,aAA0B,EAAE;IAElC,oFAAoF;IAEpF,KAAK,MAAM,CAACC,WAAW,EAAEC,SAAS,EAAE,CAAC,IAAIZ,OAAOa,OAAO,CAACd,qBAAsB;QAC5E,IAAI,CAACR,aAAaoB,cAAcnB,OAAO;YAErC;QACF;QACA,KAAK,MAAMsB,eAAeF,UAAW;YACnC,MAAMG,WAAWC,8BAA8B;gBAC7CxB,OAAOmB;gBACPM,gBAAgBH,YAAYG,cAAc;gBAC1CX;gBACAY,YAAYJ,YAAYI,UAAU;gBAClCC,gBAAgBL,YAAYK,cAAc;YAC5C;YACA,IAAIJ,UAAU;gBACZL,WAAWU,IAAI,CAACL;YAClB;QACF;IACF;IAEA,MAAMX,SAAsB,EAAE;IAC9B,MAAMC,UAAuB,EAAE;IAC/B,MAAMF,UAAuB,EAAE;IAE/B;;;GAGC,GACD,KAAK,MAAMkB,aAAaX,WAAY;QAClC,MAAM,EAAEY,MAAM,EAAE,GAAG,MAAMC,kBAAkB;YACzCF;YACA3B;YACAY;QACF;QACA,OAAQgB;YACN,KAAK;gBACHnB,QAAQiB,IAAI,CAACC;gBACb;YACF,KAAK;gBACHhB,QAAQe,IAAI,CAACC;gBACb;YACF,KAAK;gBACHjB,OAAOgB,IAAI,CAACC;gBACZ;QACJ;IACF;IACA,OAAO;QACLlB;QACAC;QACAC;IACF;AACF;AAEA,OAAO,SAASW,8BAA8B,EAC5CxB,KAAK,EACLyB,cAAc,EACdX,KAAK,EACLY,UAAU,EACVC,cAAc,EAOf;IACC,MAAMK,qBAAqBlB,OAAOA,OAAOmB,eAAeC,QAAQ,CAAClC,MAAM;IAEvE,MAAMmC,mBAAmBT,aACrBM,oBAAoBI,OAAO,CAACV,WAAWT,IAAI,CAAC,EAAEkB,mBAC9CH,oBAAoBK,WAAW,CAACV,gBAAgBV,QAAQ,GAAG,EAAEkB;IAEjE,MAAMG,UAAU,IAAI7C,KAAKgC,eAAec,IAAI,EAAE;QAC5C,iJAAiJ;QACjJC,cAAc;IAChB,GAAGF,OAAO,CAACH,oBAAoBM;IAE/B,IAAI,CAACH,SAAS;QACZ,OAAO;IACT;IACA,OAAO;QACLb;QACAC;QACAgB,WAAWJ;QACXX;IACF;AACF;AAEA,OAAO,eAAeI,kBAAkB,EACtCF,SAAS,EACT3B,GAAG,EACHY,KAAK,EAKN;IAIC,IAAI,CAACe,UAAUH,UAAU,IAAI,CAACG,UAAUF,cAAc,EAAE;QACtD,OAAO;YACLG,QAAQ;QACV;IACF;IAEA,MAAMa,mBAAmBd,UAAUJ,cAAc,CAACmB,KAAK,EAAEC;IACzD,MAAMC,kBAAkBjB,UAAUJ,cAAc,CAACmB,KAAK,EAAEG;IAExD,IAAI;QACF,MAAMC,uBAA8D,MAAM,AACxEL,CAAAA,oBAAoB/C,qBAAoB,EACxC;YACA,qFAAqF;YACrFA,uBAAuB+C,mBAAmB/C,wBAAwB;YAClEqD,UAAUnC;YACVe;YACA3B;QACF;QAEA,IAAI,CAAC8C,qBAAqBE,cAAc,EAAE;YACxC,MAAM,AAACJ,CAAAA,mBAAmBnD,oBAAmB,EAAG;gBAC9C,mFAAmF;gBACnFA,sBAAsBmD,kBAAkBnD,uBAAuB;gBAC/DsD,UAAUnC;gBACVe;gBACA3B;gBACA4B,QAAQ;YACV;YACA,OAAO;gBACLA,QAAQ;YACV;QACF;QAEA,MAAMqB,MAAO,MAAMjD,IAAIE,OAAO,CAACE,IAAI,CAACN,KAAK,CAAC;YACxCoD,OAAOJ,qBAAqBI,KAAK,IAAI,CAAC;YACtCC,MAAM;gBACJC,WAAW;YACb;YACAtD,OAAO6B,UAAUJ,cAAc,CAACzB,KAAK;YACrCE;YACAqD,MAAM1B,WAAWH,YAAYT;YAC7ByB,WAAWM,qBAAqBN,SAAS;YACzCc,UAAU3B,UAAUF,cAAc,EAAEV;QACtC;QAEA,MAAM,AAAC6B,CAAAA,mBAAmBnD,oBAAmB,EAAG;YAC9C,mFAAmF;YACnFA,sBAAsBmD,kBAAkBnD,uBAAuB;YAC/DwD;YACAF,UAAUnC;YACVe;YACA3B;YACA4B,QAAQ;QACV;QACA,OAAO;YACLA,QAAQ;QACV;IACF,EAAE,OAAO2B,OAAO;QACd,MAAM,AAACX,CAAAA,mBAAmBnD,oBAAmB,EAAG;YAC9C,mFAAmF;YACnFA,sBAAsBmD,kBAAkBnD,uBAAuB;YAC/D8D,OAAOA;YACPR,UAAUnC;YACVe;YACA3B;YACA4B,QAAQ;QACV;QACA,OAAO;YACLA,QAAQ;QACV;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/queues/operations/runJobs/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAG1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAarD,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,IAAI,CAAA;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACxC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;OAEG;IACH,wBAAwB,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,OAAO,SAAgB,WAAW,KAAG,OAAO,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/queues/operations/runJobs/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAG1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAarD,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,IAAI,CAAA;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACxC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;OAEG;IACH,wBAAwB,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,OAAO,SAAgB,WAAW,KAAG,OAAO,CAAC,aAAa,CA2dtE,CAAA"}
|
|
@@ -226,25 +226,20 @@ export const runJobs = async (args)=>{
|
|
|
226
226
|
remainingJobsFromQueried: 0
|
|
227
227
|
};
|
|
228
228
|
}
|
|
229
|
-
/**
|
|
230
|
-
* Just for logging purposes, we want to know how many jobs are new and how many are existing (= already been tried).
|
|
231
|
-
* This is only for logs - in the end we still want to run all jobs, regardless of whether they are new or existing.
|
|
232
|
-
*/ const { existingJobs, newJobs } = jobs.reduce((acc, job)=>{
|
|
233
|
-
if (job.totalTried > 0) {
|
|
234
|
-
acc.existingJobs.push(job);
|
|
235
|
-
} else {
|
|
236
|
-
acc.newJobs.push(job);
|
|
237
|
-
}
|
|
238
|
-
return acc;
|
|
239
|
-
}, {
|
|
240
|
-
existingJobs: [],
|
|
241
|
-
newJobs: []
|
|
242
|
-
});
|
|
243
229
|
if (!silent || typeof silent === 'object' && !silent.info) {
|
|
230
|
+
let newCount = 0;
|
|
231
|
+
let retryCount = 0;
|
|
232
|
+
for (const job of jobs){
|
|
233
|
+
if (job.totalTried > 0) {
|
|
234
|
+
retryCount++;
|
|
235
|
+
} else {
|
|
236
|
+
newCount++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
244
239
|
payload.logger.info({
|
|
245
240
|
msg: `Running ${jobs.length} jobs.`,
|
|
246
|
-
new:
|
|
247
|
-
retrying:
|
|
241
|
+
new: newCount,
|
|
242
|
+
retrying: retryCount
|
|
248
243
|
});
|
|
249
244
|
}
|
|
250
245
|
const successfullyCompletedJobs = [];
|
|
@@ -253,22 +248,45 @@ export const runJobs = async (args)=>{
|
|
|
253
248
|
throw new Error('Job must have either a workflowSlug or a taskSlug');
|
|
254
249
|
}
|
|
255
250
|
const jobReq = isolateObjectProperty(req, 'transactionID');
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
251
|
+
let workflowConfig = undefined;
|
|
252
|
+
if (job.workflowSlug && jobsConfig.workflows?.length) {
|
|
253
|
+
workflowConfig = jobsConfig.workflows.find(({ slug })=>slug === job.workflowSlug);
|
|
254
|
+
} else if (job.taskSlug && jobsConfig.tasks?.length) {
|
|
255
|
+
const taskExists = jobsConfig.tasks.some(({ slug })=>slug === job.taskSlug);
|
|
256
|
+
if (taskExists) {
|
|
257
|
+
workflowConfig = {
|
|
258
|
+
slug: 'singleTask',
|
|
259
|
+
handler: async ({ job, tasks })=>{
|
|
260
|
+
await tasks[job.taskSlug]('1', {
|
|
261
|
+
input: job.input
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
};
|
|
262
265
|
}
|
|
263
|
-
}
|
|
266
|
+
}
|
|
264
267
|
if (!workflowConfig) {
|
|
268
|
+
// Permanently fail jobs whose task/workflow slug is no longer registered in config — they can never complete.
|
|
269
|
+
const errorMessage = `${job.taskSlug ? `Task '${job.taskSlug}'` : `Workflow '${job.workflowSlug}'`} is not registered in payload.config.jobs.`;
|
|
270
|
+
if (!silent || typeof silent === 'object' && !silent.error) {
|
|
271
|
+
payload.logger.error({
|
|
272
|
+
msg: `Error running job ${job.workflowSlug || `Task: ${job.taskSlug}`} id: ${job.id} - ${errorMessage}`
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
const updateJob = getUpdateJobFunction(job, jobReq);
|
|
276
|
+
await updateJob({
|
|
277
|
+
error: {
|
|
278
|
+
message: errorMessage
|
|
279
|
+
},
|
|
280
|
+
hasError: true,
|
|
281
|
+
processing: false,
|
|
282
|
+
totalTried: (job.totalTried ?? 0) + 1
|
|
283
|
+
});
|
|
265
284
|
return {
|
|
266
285
|
id: job.id,
|
|
267
286
|
result: {
|
|
268
|
-
status: 'error'
|
|
287
|
+
status: 'error-reached-max-retries'
|
|
269
288
|
}
|
|
270
|
-
}
|
|
271
|
-
;
|
|
289
|
+
};
|
|
272
290
|
}
|
|
273
291
|
try {
|
|
274
292
|
const updateJob = getUpdateJobFunction(job, jobReq);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/queues/operations/runJobs/index.ts"],"sourcesContent":["import type { Job } from '../../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../../types/index.js'\nimport type { WorkflowJSON } from '../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig, WorkflowHandler } from '../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../localAPI.js'\nimport type { RunJobResult } from './runJob/index.js'\n\nimport { Forbidden } from '../../../errors/Forbidden.js'\nimport { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js'\nimport { jobsCollectionSlug } from '../../config/collection.js'\nimport { JobCancelledError } from '../../errors/index.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\nimport { updateJob, updateJobs } from '../../utilities/updateJob.js'\nimport { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js'\nimport { importHandlerPath } from './runJob/importHandlerPath.js'\nimport { runJob } from './runJob/index.js'\nimport { runJSONJob } from './runJSONJob/index.js'\n\nexport type RunJobsArgs = {\n /**\n * If you want to run jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * ID of the job to run\n */\n id?: number | string\n /**\n * The maximum number of jobs to run in this invocation\n *\n * @default 10\n */\n limit?: number\n overrideAccess?: boolean\n /**\n * Adjust the job processing order\n *\n * FIFO would equal `createdAt` and LIFO would equal `-createdAt`.\n *\n * @default all jobs for all queues will be executed in FIFO order.\n */\n processingOrder?: Sort\n /**\n * If you want to run jobs from a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n /**\n * By default, jobs are run in parallel.\n * If you want to run them in sequence, set this to true.\n */\n sequential?: boolean\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n where?: Where\n}\n\nexport type RunJobsResult = {\n jobStatus?: Record<string, RunJobResult>\n /**\n * If this is true, there for sure are no jobs remaining, regardless of the limit\n */\n noJobsRemaining?: boolean\n /**\n * Out of the jobs that were queried & processed (within the set limit), how many are remaining and retryable?\n */\n remainingJobsFromQueried: number\n}\n\nexport const runJobs = async (args: RunJobsArgs): Promise<RunJobsResult> => {\n const {\n id,\n allQueues = false,\n limit = 10,\n overrideAccess,\n processingOrder,\n queue = 'default',\n req,\n req: {\n payload,\n payload: {\n config: { jobs: jobsConfig },\n },\n },\n sequential,\n silent = false,\n where: whereFromProps,\n } = args\n\n if (!overrideAccess) {\n /**\n * By default, jobsConfig.access.run will be `defaultAccess` which is a function that returns `true` if the user is logged in.\n */\n const accessFn = jobsConfig?.access?.run ?? (() => true)\n const hasAccess = await accessFn({ req })\n if (!hasAccess) {\n throw new Forbidden(req.t)\n }\n }\n const and: Where[] = [\n {\n completedAt: {\n exists: false,\n },\n },\n {\n hasError: {\n not_equals: true,\n },\n },\n {\n processing: {\n equals: false,\n },\n },\n {\n or: [\n {\n waitUntil: {\n exists: false,\n },\n },\n {\n waitUntil: {\n less_than: getCurrentDate().toISOString(),\n },\n },\n ],\n },\n ]\n\n if (allQueues !== true) {\n and.push({\n queue: {\n equals: queue ?? 'default',\n },\n })\n }\n\n if (whereFromProps) {\n and.push(whereFromProps)\n }\n\n // Only enforce concurrency controls if the feature is enabled\n if (jobsConfig.enableConcurrencyControl) {\n // Find currently running jobs with concurrency keys to enforce exclusive concurrency\n // Jobs with the same concurrencyKey should not run in parallel\n const runningJobsWithConcurrency = await payload.db.find({\n collection: jobsCollectionSlug,\n limit: 0,\n pagination: false,\n req: { transactionID: undefined },\n select: {\n concurrencyKey: true,\n },\n where: {\n and: [{ processing: { equals: true } }, { concurrencyKey: { exists: true } }],\n },\n })\n\n const runningConcurrencyKeys = new Set<string>()\n if (runningJobsWithConcurrency?.docs) {\n for (const doc of runningJobsWithConcurrency.docs) {\n const concurrencyKey = (doc as Job).concurrencyKey\n if (concurrencyKey) {\n runningConcurrencyKeys.add(concurrencyKey)\n }\n }\n }\n\n // Exclude jobs whose concurrencyKey is already running\n if (runningConcurrencyKeys.size > 0) {\n and.push({\n or: [\n // Jobs without a concurrency key can always run\n { concurrencyKey: { exists: false } },\n // Jobs with a concurrency key that is not currently running can run\n { concurrencyKey: { not_in: [...runningConcurrencyKeys] } },\n ],\n })\n }\n }\n\n // Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of\n // the same job being picked up by another worker\n let jobs: Job[] = []\n\n if (id) {\n // Only one job to run\n const job = await updateJob({\n id,\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n req,\n returning: true,\n })\n if (job) {\n jobs = [job]\n }\n } else {\n let defaultProcessingOrder: Sort =\n payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt'\n\n const processingOrderConfig = jobsConfig.processingOrder\n if (typeof processingOrderConfig === 'function') {\n defaultProcessingOrder = await processingOrderConfig(args)\n } else if (typeof processingOrderConfig === 'object' && !Array.isArray(processingOrderConfig)) {\n if (\n !allQueues &&\n queue &&\n processingOrderConfig.queues &&\n processingOrderConfig.queues[queue]\n ) {\n defaultProcessingOrder = processingOrderConfig.queues[queue]\n } else if (processingOrderConfig.default) {\n defaultProcessingOrder = processingOrderConfig.default\n }\n } else if (typeof processingOrderConfig === 'string') {\n defaultProcessingOrder = processingOrderConfig\n }\n const updatedDocs = await updateJobs({\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n limit,\n req,\n returning: true,\n sort: processingOrder ?? defaultProcessingOrder,\n where: { and },\n })\n\n if (updatedDocs) {\n jobs = updatedDocs\n }\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: true,\n remainingJobsFromQueried: 0,\n }\n }\n\n // Only handle concurrency deduplication if the feature is enabled\n if (jobsConfig.enableConcurrencyControl) {\n // Handle the case where multiple jobs with the same concurrencyKey were picked up in the same batch\n // We should only run one job per concurrencyKey, release the others back to pending\n const seenConcurrencyKeys = new Set<string>()\n const jobsToRun: Job[] = []\n const jobsToRelease: Job[] = []\n\n for (const job of jobs) {\n if (job.concurrencyKey) {\n if (seenConcurrencyKeys.has(job.concurrencyKey)) {\n // This job has the same concurrencyKey as another job we're already running\n jobsToRelease.push(job)\n } else {\n seenConcurrencyKeys.add(job.concurrencyKey)\n jobsToRun.push(job)\n }\n } else {\n jobsToRun.push(job)\n }\n }\n\n // Release duplicate concurrencyKey jobs back to pending state\n if (jobsToRelease.length > 0) {\n const releaseIds = jobsToRelease.map((job) => job.id)\n await updateJobs({\n data: { processing: false },\n disableTransaction: true,\n req,\n returning: false,\n where: { id: { in: releaseIds } },\n })\n }\n\n // Use only the filtered jobs going forward\n jobs = jobsToRun\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: false,\n remainingJobsFromQueried: 0,\n }\n }\n\n /**\n * Just for logging purposes, we want to know how many jobs are new and how many are existing (= already been tried).\n * This is only for logs - in the end we still want to run all jobs, regardless of whether they are new or existing.\n */\n const { existingJobs, newJobs } = jobs.reduce(\n (acc, job) => {\n if (job.totalTried > 0) {\n acc.existingJobs.push(job)\n } else {\n acc.newJobs.push(job)\n }\n return acc\n },\n { existingJobs: [] as Job[], newJobs: [] as Job[] },\n )\n\n if (!silent || (typeof silent === 'object' && !silent.info)) {\n payload.logger.info({\n msg: `Running ${jobs.length} jobs.`,\n new: newJobs?.length,\n retrying: existingJobs?.length,\n })\n }\n\n const successfullyCompletedJobs: (number | string)[] = []\n\n const runSingleJob = async (\n job: Job,\n ): Promise<{\n id: number | string\n result: RunJobResult\n }> => {\n if (!job.workflowSlug && !job.taskSlug) {\n throw new Error('Job must have either a workflowSlug or a taskSlug')\n }\n const jobReq = isolateObjectProperty(req, 'transactionID')\n\n const workflowConfig: WorkflowConfig =\n job.workflowSlug && jobsConfig.workflows?.length\n ? jobsConfig.workflows.find(({ slug }) => slug === job.workflowSlug)!\n : {\n slug: 'singleTask',\n handler: async ({ job, tasks }) => {\n await tasks[job.taskSlug as string]!('1', {\n input: job.input,\n })\n },\n }\n\n if (!workflowConfig) {\n return {\n id: job.id,\n result: {\n status: 'error',\n },\n } // Skip jobs with no workflow configuration\n }\n\n try {\n const updateJob = getUpdateJobFunction(job, jobReq)\n\n // the runner will either be passed to the config\n // OR it will be a path, which we will need to import via eval to avoid\n // Next.js compiler dynamic import expression errors\n let workflowHandler: WorkflowHandler | WorkflowJSON\n if (\n typeof workflowConfig.handler === 'function' ||\n (typeof workflowConfig.handler === 'object' && Array.isArray(workflowConfig.handler))\n ) {\n workflowHandler = workflowConfig.handler\n } else {\n workflowHandler = await importHandlerPath<typeof workflowHandler>(workflowConfig.handler)\n\n if (!workflowHandler) {\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n const errorMessage = `Can't find runner while importing with the path ${workflowConfig.handler} in job type ${jobLabel}.`\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error(errorMessage)\n }\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n processing: false,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n }\n\n if (typeof workflowHandler === 'function') {\n const result = await runJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n } else {\n const result = await runJSONJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n }\n } catch (error) {\n if (error instanceof JobCancelledError) {\n if (\n !(job.error as Record<string, unknown> | undefined)?.cancelled ||\n !job.hasError ||\n job.processing ||\n job.completedAt ||\n job.waitUntil\n ) {\n // When using the local API to cancel jobs, the local API will update the job data for us to ensure the job is cancelled.\n // But when throwing a JobCancelledError within a task or workflow handler, we are responsible for updating the job data ourselves.\n await updateJob({\n id: job.id,\n data: {\n completedAt: null,\n error: {\n cancelled: true,\n message: error.message,\n },\n hasError: true,\n processing: false,\n waitUntil: null,\n },\n depth: 0,\n disableTransaction: true,\n req,\n returning: false,\n })\n }\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n throw error\n }\n }\n\n let resultsArray: { id: number | string; result: RunJobResult }[] = []\n if (sequential) {\n for (const job of jobs) {\n const result = await runSingleJob(job)\n if (result) {\n resultsArray.push(result)\n }\n }\n } else {\n const jobPromises = jobs.map(runSingleJob)\n resultsArray = (await Promise.all(jobPromises)) as {\n id: number | string\n result: RunJobResult\n }[]\n }\n\n if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {\n try {\n if (jobsConfig.runHooks) {\n await payload.delete({\n collection: jobsCollectionSlug,\n depth: 0, // can be 0 since we're not returning anything\n disableTransaction: true,\n where: { id: { in: successfullyCompletedJobs } },\n })\n } else {\n await payload.db.deleteMany({\n collection: jobsCollectionSlug,\n where: { id: { in: successfullyCompletedJobs } },\n })\n }\n } catch (err) {\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n err,\n msg: `Failed to delete jobs ${successfullyCompletedJobs.join(', ')} on complete`,\n })\n }\n }\n }\n\n const resultsObject: RunJobsResult['jobStatus'] = resultsArray.reduce(\n (acc, cur) => {\n if (cur !== null) {\n // Check if there's a valid result to include\n acc[cur.id] = cur.result\n }\n return acc\n },\n {} as Record<string, RunJobResult>,\n )\n\n let remainingJobsFromQueried = 0\n for (const jobID in resultsObject) {\n const jobResult = resultsObject[jobID]\n if (jobResult?.status === 'error') {\n remainingJobsFromQueried++ // Can be retried\n }\n }\n\n return {\n jobStatus: resultsObject,\n remainingJobsFromQueried,\n }\n}\n"],"names":["Forbidden","isolateObjectProperty","jobsCollectionSlug","JobCancelledError","getCurrentDate","updateJob","updateJobs","getUpdateJobFunction","importHandlerPath","runJob","runJSONJob","runJobs","args","id","allQueues","limit","overrideAccess","processingOrder","queue","req","payload","config","jobs","jobsConfig","sequential","silent","where","whereFromProps","accessFn","access","run","hasAccess","t","and","completedAt","exists","hasError","not_equals","processing","equals","or","waitUntil","less_than","toISOString","push","enableConcurrencyControl","runningJobsWithConcurrency","db","find","collection","pagination","transactionID","undefined","select","concurrencyKey","runningConcurrencyKeys","Set","docs","doc","add","size","not_in","job","data","depth","disableTransaction","returning","defaultProcessingOrder","collections","defaultSort","processingOrderConfig","Array","isArray","queues","default","updatedDocs","sort","length","noJobsRemaining","remainingJobsFromQueried","seenConcurrencyKeys","jobsToRun","jobsToRelease","has","releaseIds","map","in","existingJobs","newJobs","reduce","acc","totalTried","info","logger","msg","new","retrying","successfullyCompletedJobs","runSingleJob","workflowSlug","taskSlug","Error","jobReq","workflowConfig","workflows","slug","handler","tasks","input","result","status","workflowHandler","jobLabel","errorMessage","error","cancelled","message","resultsArray","jobPromises","Promise","all","deleteJobOnComplete","runHooks","delete","deleteMany","err","join","resultsObject","cur","jobID","jobResult","jobStatus"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/queues/operations/runJobs/index.ts"],"sourcesContent":["import type { Job } from '../../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../../types/index.js'\nimport type { WorkflowJSON } from '../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig, WorkflowHandler } from '../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../localAPI.js'\nimport type { RunJobResult } from './runJob/index.js'\n\nimport { Forbidden } from '../../../errors/Forbidden.js'\nimport { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js'\nimport { jobsCollectionSlug } from '../../config/collection.js'\nimport { JobCancelledError } from '../../errors/index.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\nimport { updateJob, updateJobs } from '../../utilities/updateJob.js'\nimport { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js'\nimport { importHandlerPath } from './runJob/importHandlerPath.js'\nimport { runJob } from './runJob/index.js'\nimport { runJSONJob } from './runJSONJob/index.js'\n\nexport type RunJobsArgs = {\n /**\n * If you want to run jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * ID of the job to run\n */\n id?: number | string\n /**\n * The maximum number of jobs to run in this invocation\n *\n * @default 10\n */\n limit?: number\n overrideAccess?: boolean\n /**\n * Adjust the job processing order\n *\n * FIFO would equal `createdAt` and LIFO would equal `-createdAt`.\n *\n * @default all jobs for all queues will be executed in FIFO order.\n */\n processingOrder?: Sort\n /**\n * If you want to run jobs from a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n /**\n * By default, jobs are run in parallel.\n * If you want to run them in sequence, set this to true.\n */\n sequential?: boolean\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n where?: Where\n}\n\nexport type RunJobsResult = {\n jobStatus?: Record<string, RunJobResult>\n /**\n * If this is true, there for sure are no jobs remaining, regardless of the limit\n */\n noJobsRemaining?: boolean\n /**\n * Out of the jobs that were queried & processed (within the set limit), how many are remaining and retryable?\n */\n remainingJobsFromQueried: number\n}\n\nexport const runJobs = async (args: RunJobsArgs): Promise<RunJobsResult> => {\n const {\n id,\n allQueues = false,\n limit = 10,\n overrideAccess,\n processingOrder,\n queue = 'default',\n req,\n req: {\n payload,\n payload: {\n config: { jobs: jobsConfig },\n },\n },\n sequential,\n silent = false,\n where: whereFromProps,\n } = args\n\n if (!overrideAccess) {\n /**\n * By default, jobsConfig.access.run will be `defaultAccess` which is a function that returns `true` if the user is logged in.\n */\n const accessFn = jobsConfig?.access?.run ?? (() => true)\n const hasAccess = await accessFn({ req })\n if (!hasAccess) {\n throw new Forbidden(req.t)\n }\n }\n const and: Where[] = [\n {\n completedAt: {\n exists: false,\n },\n },\n {\n hasError: {\n not_equals: true,\n },\n },\n {\n processing: {\n equals: false,\n },\n },\n {\n or: [\n {\n waitUntil: {\n exists: false,\n },\n },\n {\n waitUntil: {\n less_than: getCurrentDate().toISOString(),\n },\n },\n ],\n },\n ]\n\n if (allQueues !== true) {\n and.push({\n queue: {\n equals: queue ?? 'default',\n },\n })\n }\n\n if (whereFromProps) {\n and.push(whereFromProps)\n }\n\n // Only enforce concurrency controls if the feature is enabled\n if (jobsConfig.enableConcurrencyControl) {\n // Find currently running jobs with concurrency keys to enforce exclusive concurrency\n // Jobs with the same concurrencyKey should not run in parallel\n const runningJobsWithConcurrency = await payload.db.find({\n collection: jobsCollectionSlug,\n limit: 0,\n pagination: false,\n req: { transactionID: undefined },\n select: {\n concurrencyKey: true,\n },\n where: {\n and: [{ processing: { equals: true } }, { concurrencyKey: { exists: true } }],\n },\n })\n\n const runningConcurrencyKeys = new Set<string>()\n if (runningJobsWithConcurrency?.docs) {\n for (const doc of runningJobsWithConcurrency.docs) {\n const concurrencyKey = (doc as Job).concurrencyKey\n if (concurrencyKey) {\n runningConcurrencyKeys.add(concurrencyKey)\n }\n }\n }\n\n // Exclude jobs whose concurrencyKey is already running\n if (runningConcurrencyKeys.size > 0) {\n and.push({\n or: [\n // Jobs without a concurrency key can always run\n { concurrencyKey: { exists: false } },\n // Jobs with a concurrency key that is not currently running can run\n { concurrencyKey: { not_in: [...runningConcurrencyKeys] } },\n ],\n })\n }\n }\n\n // Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of\n // the same job being picked up by another worker\n let jobs: Job[] = []\n\n if (id) {\n // Only one job to run\n const job = await updateJob({\n id,\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n req,\n returning: true,\n })\n if (job) {\n jobs = [job]\n }\n } else {\n let defaultProcessingOrder: Sort =\n payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt'\n\n const processingOrderConfig = jobsConfig.processingOrder\n if (typeof processingOrderConfig === 'function') {\n defaultProcessingOrder = await processingOrderConfig(args)\n } else if (typeof processingOrderConfig === 'object' && !Array.isArray(processingOrderConfig)) {\n if (\n !allQueues &&\n queue &&\n processingOrderConfig.queues &&\n processingOrderConfig.queues[queue]\n ) {\n defaultProcessingOrder = processingOrderConfig.queues[queue]\n } else if (processingOrderConfig.default) {\n defaultProcessingOrder = processingOrderConfig.default\n }\n } else if (typeof processingOrderConfig === 'string') {\n defaultProcessingOrder = processingOrderConfig\n }\n const updatedDocs = await updateJobs({\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n limit,\n req,\n returning: true,\n sort: processingOrder ?? defaultProcessingOrder,\n where: { and },\n })\n\n if (updatedDocs) {\n jobs = updatedDocs\n }\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: true,\n remainingJobsFromQueried: 0,\n }\n }\n\n // Only handle concurrency deduplication if the feature is enabled\n if (jobsConfig.enableConcurrencyControl) {\n // Handle the case where multiple jobs with the same concurrencyKey were picked up in the same batch\n // We should only run one job per concurrencyKey, release the others back to pending\n const seenConcurrencyKeys = new Set<string>()\n const jobsToRun: Job[] = []\n const jobsToRelease: Job[] = []\n\n for (const job of jobs) {\n if (job.concurrencyKey) {\n if (seenConcurrencyKeys.has(job.concurrencyKey)) {\n // This job has the same concurrencyKey as another job we're already running\n jobsToRelease.push(job)\n } else {\n seenConcurrencyKeys.add(job.concurrencyKey)\n jobsToRun.push(job)\n }\n } else {\n jobsToRun.push(job)\n }\n }\n\n // Release duplicate concurrencyKey jobs back to pending state\n if (jobsToRelease.length > 0) {\n const releaseIds = jobsToRelease.map((job) => job.id)\n await updateJobs({\n data: { processing: false },\n disableTransaction: true,\n req,\n returning: false,\n where: { id: { in: releaseIds } },\n })\n }\n\n // Use only the filtered jobs going forward\n jobs = jobsToRun\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: false,\n remainingJobsFromQueried: 0,\n }\n }\n\n if (!silent || (typeof silent === 'object' && !silent.info)) {\n let newCount = 0\n let retryCount = 0\n\n for (const job of jobs) {\n if (job.totalTried > 0) {\n retryCount++\n } else {\n newCount++\n }\n }\n\n payload.logger.info({\n msg: `Running ${jobs.length} jobs.`,\n new: newCount,\n retrying: retryCount,\n })\n }\n\n const successfullyCompletedJobs: (number | string)[] = []\n\n const runSingleJob = async (\n job: Job,\n ): Promise<{\n id: number | string\n result: RunJobResult\n }> => {\n if (!job.workflowSlug && !job.taskSlug) {\n throw new Error('Job must have either a workflowSlug or a taskSlug')\n }\n const jobReq = isolateObjectProperty(req, 'transactionID')\n\n let workflowConfig: undefined | WorkflowConfig = undefined\n\n if (job.workflowSlug && jobsConfig.workflows?.length) {\n workflowConfig = jobsConfig.workflows.find(({ slug }) => slug === job.workflowSlug)\n } else if (job.taskSlug && jobsConfig.tasks?.length) {\n const taskExists = jobsConfig.tasks.some(({ slug }) => slug === job.taskSlug)\n if (taskExists) {\n workflowConfig = {\n slug: 'singleTask',\n handler: async ({ job, tasks }) => {\n await tasks[job.taskSlug as string]!('1', {\n input: job.input,\n })\n },\n }\n }\n }\n\n if (!workflowConfig) {\n // Permanently fail jobs whose task/workflow slug is no longer registered in config — they can never complete.\n const errorMessage = `${job.taskSlug ? `Task '${job.taskSlug}'` : `Workflow '${job.workflowSlug}'`} is not registered in payload.config.jobs.`\n\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n msg: `Error running job ${job.workflowSlug || `Task: ${job.taskSlug}`} id: ${job.id} - ${errorMessage}`,\n })\n }\n\n const updateJob = getUpdateJobFunction(job, jobReq)\n await updateJob({\n error: { message: errorMessage },\n hasError: true,\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n\n try {\n const updateJob = getUpdateJobFunction(job, jobReq)\n\n // the runner will either be passed to the config\n // OR it will be a path, which we will need to import via eval to avoid\n // Next.js compiler dynamic import expression errors\n let workflowHandler: WorkflowHandler | WorkflowJSON\n if (\n typeof workflowConfig.handler === 'function' ||\n (typeof workflowConfig.handler === 'object' && Array.isArray(workflowConfig.handler))\n ) {\n workflowHandler = workflowConfig.handler\n } else {\n workflowHandler = await importHandlerPath<typeof workflowHandler>(workflowConfig.handler)\n\n if (!workflowHandler) {\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n const errorMessage = `Can't find runner while importing with the path ${workflowConfig.handler} in job type ${jobLabel}.`\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error(errorMessage)\n }\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n processing: false,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n }\n\n if (typeof workflowHandler === 'function') {\n const result = await runJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n } else {\n const result = await runJSONJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n }\n } catch (error) {\n if (error instanceof JobCancelledError) {\n if (\n !(job.error as Record<string, unknown> | undefined)?.cancelled ||\n !job.hasError ||\n job.processing ||\n job.completedAt ||\n job.waitUntil\n ) {\n // When using the local API to cancel jobs, the local API will update the job data for us to ensure the job is cancelled.\n // But when throwing a JobCancelledError within a task or workflow handler, we are responsible for updating the job data ourselves.\n await updateJob({\n id: job.id,\n data: {\n completedAt: null,\n error: {\n cancelled: true,\n message: error.message,\n },\n hasError: true,\n processing: false,\n waitUntil: null,\n },\n depth: 0,\n disableTransaction: true,\n req,\n returning: false,\n })\n }\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n throw error\n }\n }\n\n let resultsArray: { id: number | string; result: RunJobResult }[] = []\n if (sequential) {\n for (const job of jobs) {\n const result = await runSingleJob(job)\n if (result) {\n resultsArray.push(result)\n }\n }\n } else {\n const jobPromises = jobs.map(runSingleJob)\n resultsArray = (await Promise.all(jobPromises)) as {\n id: number | string\n result: RunJobResult\n }[]\n }\n\n if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {\n try {\n if (jobsConfig.runHooks) {\n await payload.delete({\n collection: jobsCollectionSlug,\n depth: 0, // can be 0 since we're not returning anything\n disableTransaction: true,\n where: { id: { in: successfullyCompletedJobs } },\n })\n } else {\n await payload.db.deleteMany({\n collection: jobsCollectionSlug,\n where: { id: { in: successfullyCompletedJobs } },\n })\n }\n } catch (err) {\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n err,\n msg: `Failed to delete jobs ${successfullyCompletedJobs.join(', ')} on complete`,\n })\n }\n }\n }\n\n const resultsObject: RunJobsResult['jobStatus'] = resultsArray.reduce(\n (acc, cur) => {\n if (cur !== null) {\n // Check if there's a valid result to include\n acc[cur.id] = cur.result\n }\n return acc\n },\n {} as Record<string, RunJobResult>,\n )\n\n let remainingJobsFromQueried = 0\n for (const jobID in resultsObject) {\n const jobResult = resultsObject[jobID]\n if (jobResult?.status === 'error') {\n remainingJobsFromQueried++ // Can be retried\n }\n }\n\n return {\n jobStatus: resultsObject,\n remainingJobsFromQueried,\n }\n}\n"],"names":["Forbidden","isolateObjectProperty","jobsCollectionSlug","JobCancelledError","getCurrentDate","updateJob","updateJobs","getUpdateJobFunction","importHandlerPath","runJob","runJSONJob","runJobs","args","id","allQueues","limit","overrideAccess","processingOrder","queue","req","payload","config","jobs","jobsConfig","sequential","silent","where","whereFromProps","accessFn","access","run","hasAccess","t","and","completedAt","exists","hasError","not_equals","processing","equals","or","waitUntil","less_than","toISOString","push","enableConcurrencyControl","runningJobsWithConcurrency","db","find","collection","pagination","transactionID","undefined","select","concurrencyKey","runningConcurrencyKeys","Set","docs","doc","add","size","not_in","job","data","depth","disableTransaction","returning","defaultProcessingOrder","collections","defaultSort","processingOrderConfig","Array","isArray","queues","default","updatedDocs","sort","length","noJobsRemaining","remainingJobsFromQueried","seenConcurrencyKeys","jobsToRun","jobsToRelease","has","releaseIds","map","in","info","newCount","retryCount","totalTried","logger","msg","new","retrying","successfullyCompletedJobs","runSingleJob","workflowSlug","taskSlug","Error","jobReq","workflowConfig","workflows","slug","tasks","taskExists","some","handler","input","errorMessage","error","message","result","status","workflowHandler","jobLabel","cancelled","resultsArray","jobPromises","Promise","all","deleteJobOnComplete","runHooks","delete","deleteMany","err","join","resultsObject","reduce","acc","cur","jobID","jobResult","jobStatus"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,4CAA4C,CAAA;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOtD,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,GAAG,CAAA;IACR,GAAG,EAAE,cAAc,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,cAAc,EAAE,cAAc,CAAA;IAC9B,eAAe,EAAE,YAAY,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,UAAU,sEAOpB,IAAI,KAAG,OAAO,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,4CAA4C,CAAA;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOtD,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,GAAG,CAAA;IACR,GAAG,EAAE,cAAc,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,cAAc,EAAE,cAAc,CAAA;IAC9B,eAAe,EAAE,YAAY,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,UAAU,sEAOpB,IAAI,KAAG,OAAO,CAAC,gBAAgB,CAwGjC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"sourcesContent":["import type { Job } from '../../../../index.js'\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type { WorkflowJSON, WorkflowStep } from '../../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig } from '../../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../../localAPI.js'\nimport type { UpdateJobFunction } from '../runJob/getUpdateJobFunction.js'\nimport type { JobRunStatus } from '../runJob/index.js'\n\nimport { handleWorkflowError } from '../../../errors/handleWorkflowError.js'\nimport { WorkflowError } from '../../../errors/index.js'\nimport { getCurrentDate } from '../../../utilities/getCurrentDate.js'\nimport { getRunTaskFunction } from '../runJob/getRunTaskFunction.js'\n\ntype Args = {\n job: Job\n req: PayloadRequest\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n updateJob: UpdateJobFunction\n workflowConfig: WorkflowConfig\n workflowHandler: WorkflowJSON\n}\n\nexport type RunJSONJobResult = {\n status: JobRunStatus\n}\n\nexport const runJSONJob = async ({\n job,\n req,\n silent = false,\n updateJob,\n workflowConfig,\n workflowHandler,\n}: Args): Promise<RunJSONJobResult> => {\n const stepsToRun: WorkflowStep<string>[] = []\n\n for (const step of workflowHandler) {\n if ('task' in step) {\n if (job?.taskStatus?.[step.task]?.[step.id]?.complete) {\n continue\n }\n } else {\n if (job?.taskStatus?.['inline']?.[step.id]?.complete) {\n continue\n }\n }\n if (step.condition && !step.condition({ job })) {\n continue\n }\n stepsToRun.push(step)\n }\n\n const tasks = getRunTaskFunction(job, workflowConfig, req, false, updateJob)\n const inlineTask = getRunTaskFunction(job, workflowConfig, req, true, updateJob)\n\n // Run the job\n try {\n await Promise.all(\n stepsToRun.map(async (step) => {\n if ('task' in step) {\n await tasks[step.task]!(step.id, {\n input: step.input ? step.input({ job }) : {},\n retries: step.retries,\n })\n } else {\n await inlineTask(step.id, {\n retries: step.retries,\n task: step.inlineTask as any, // TODO: Fix type\n })\n }\n }),\n )\n } catch (error) {\n const { hasFinalError } = await handleWorkflowError({\n error:\n error instanceof WorkflowError\n ? error\n : new WorkflowError({\n job,\n message:\n typeof error === 'object' && error && 'message' in error\n ? (error.message as string)\n : 'An unhandled error occurred',\n workflowConfig,\n }),\n silent,\n\n req,\n updateJob,\n })\n\n return {\n status: hasFinalError ? 'error-reached-max-retries' : 'error',\n }\n }\n\n // Check if workflow has completed\n let workflowCompleted = false\n for (const [slug, map] of Object.entries(job.taskStatus)) {\n for (const [id, taskStatus] of Object.entries(map)) {\n if (taskStatus.complete) {\n const step = workflowHandler.find((step) => {\n if ('task' in step) {\n return step.task === slug && step.id === id\n } else {\n return step.id === id && slug === 'inline'\n }\n })\n if (step?.completesJob) {\n workflowCompleted = true\n break\n }\n }\n }\n }\n\n if (workflowCompleted) {\n await updateJob({\n completedAt: getCurrentDate().toISOString(),\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n status: 'success',\n }\n } else {\n // Retry the job - no need to bump processing or totalTried as this does not count as a retry. A condition of a different task might have just opened up!\n return await runJSONJob({\n job,\n req,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n }\n}\n"],"names":["handleWorkflowError","WorkflowError","getCurrentDate","getRunTaskFunction","runJSONJob","job","req","silent","updateJob","workflowConfig","workflowHandler","stepsToRun","step","taskStatus","task","id","complete","condition","push","tasks","inlineTask","Promise","all","map","input","retries","error","hasFinalError","message","status","workflowCompleted","slug","Object","entries","find","completesJob","completedAt","toISOString","processing","totalTried"],"mappings":"AAQA,SAASA,mBAAmB,QAAQ,yCAAwC;AAC5E,SAASC,aAAa,QAAQ,2BAA0B;AACxD,SAASC,cAAc,QAAQ,uCAAsC;AACrE,SAASC,kBAAkB,QAAQ,kCAAiC;AAuBpE,OAAO,MAAMC,aAAa,OAAO,EAC/BC,GAAG,EACHC,GAAG,EACHC,SAAS,KAAK,EACdC,SAAS,EACTC,cAAc,EACdC,eAAe,EACV;IACL,MAAMC,aAAqC,EAAE;IAE7C,KAAK,MAAMC,QAAQF,gBAAiB;QAClC,IAAI,UAAUE,MAAM;YAClB,IAAIP,KAAKQ,YAAY,CAACD,KAAKE,IAAI,CAAC,EAAE,CAACF,KAAKG,EAAE,CAAC,EAAEC,UAAU;gBACrD;YACF;QACF,OAAO;YACL,IAAIX,KAAKQ,YAAY,CAAC,SAAS,EAAE,CAACD,KAAKG,EAAE,CAAC,EAAEC,UAAU;gBACpD;YACF;QACF;QACA,IAAIJ,KAAKK,SAAS,IAAI,CAACL,KAAKK,SAAS,CAAC;YAAEZ;QAAI,IAAI;YAC9C;QACF;QACAM,WAAWO,IAAI,CAACN;IAClB;IAEA,MAAMO,QAAQhB,mBAAmBE,KAAKI,gBAAgBH,KAAK,OAAOE;IAClE,MAAMY,aAAajB,mBAAmBE,KAAKI,gBAAgBH,KAAK,MAAME;IAEtE,cAAc;IACd,IAAI;QACF,MAAMa,QAAQC,GAAG,CACfX,WAAWY,GAAG,CAAC,OAAOX;YACpB,IAAI,UAAUA,MAAM;gBAClB,MAAMO,KAAK,CAACP,KAAKE,IAAI,CAAC,CAAEF,KAAKG,EAAE,EAAE;oBAC/BS,OAAOZ,KAAKY,KAAK,GAAGZ,KAAKY,KAAK,CAAC;wBAAEnB;oBAAI,KAAK,CAAC;oBAC3CoB,SAASb,KAAKa,OAAO;gBACvB;YACF,OAAO;gBACL,MAAML,WAAWR,KAAKG,EAAE,EAAE;oBACxBU,SAASb,KAAKa,OAAO;oBACrBX,MAAMF,KAAKQ,UAAU;gBACvB;YACF;QACF;IAEJ,EAAE,OAAOM,OAAO;QACd,MAAM,EAAEC,aAAa,EAAE,GAAG,MAAM3B,oBAAoB;YAClD0B,OACEA,iBAAiBzB,gBACbyB,QACA,IAAIzB,cAAc;gBAChBI;gBACAuB,SACE,OAAOF,UAAU,YAAYA,SAAS,aAAaA,QAC9CA,MAAME,OAAO,GACd;gBACNnB;YACF;YACNF;YAEAD;YACAE;QACF;QAEA,OAAO;YACLqB,QAAQF,gBAAgB,8BAA8B;QACxD;IACF;IAEA,kCAAkC;IAClC,IAAIG,oBAAoB;IACxB,KAAK,MAAM,CAACC,MAAMR,IAAI,IAAIS,OAAOC,OAAO,CAAC5B,IAAIQ,UAAU,EAAG;QACxD,KAAK,MAAM,CAACE,IAAIF,WAAW,IAAImB,OAAOC,OAAO,CAACV,KAAM;YAClD,IAAIV,WAAWG,QAAQ,EAAE;gBACvB,MAAMJ,OAAOF,gBAAgBwB,IAAI,CAAC,CAACtB;oBACjC,IAAI,UAAUA,MAAM;wBAClB,OAAOA,KAAKE,IAAI,KAAKiB,QAAQnB,KAAKG,EAAE,KAAKA;oBAC3C,OAAO;wBACL,OAAOH,KAAKG,EAAE,KAAKA,MAAMgB,SAAS;oBACpC;gBACF;gBACA,IAAInB,MAAMuB,cAAc;oBACtBL,oBAAoB;oBACpB;gBACF;YACF;QACF;IACF;IAEA,IAAIA,mBAAmB;QACrB,MAAMtB,UAAU;YACd4B,aAAalC,iBAAiBmC,WAAW;YACzCC,YAAY;YACZC,YAAY,AAAClC,CAAAA,IAAIkC,UAAU,IAAI,CAAA,IAAK;QACtC;QAEA,OAAO;YACLV,QAAQ;QACV;IACF,OAAO;QACL,yJAAyJ;QACzJ,OAAO,MAAMzB,WAAW;YACtBC;YACAC;
|
|
1
|
+
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"sourcesContent":["import type { Job } from '../../../../index.js'\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type { WorkflowJSON, WorkflowStep } from '../../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig } from '../../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../../localAPI.js'\nimport type { UpdateJobFunction } from '../runJob/getUpdateJobFunction.js'\nimport type { JobRunStatus } from '../runJob/index.js'\n\nimport { handleWorkflowError } from '../../../errors/handleWorkflowError.js'\nimport { WorkflowError } from '../../../errors/index.js'\nimport { getCurrentDate } from '../../../utilities/getCurrentDate.js'\nimport { getRunTaskFunction } from '../runJob/getRunTaskFunction.js'\n\ntype Args = {\n job: Job\n req: PayloadRequest\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n updateJob: UpdateJobFunction\n workflowConfig: WorkflowConfig\n workflowHandler: WorkflowJSON\n}\n\nexport type RunJSONJobResult = {\n status: JobRunStatus\n}\n\nexport const runJSONJob = async ({\n job,\n req,\n silent = false,\n updateJob,\n workflowConfig,\n workflowHandler,\n}: Args): Promise<RunJSONJobResult> => {\n const stepsToRun: WorkflowStep<string>[] = []\n\n for (const step of workflowHandler) {\n if ('task' in step) {\n if (job?.taskStatus?.[step.task]?.[step.id]?.complete) {\n continue\n }\n } else {\n if (job?.taskStatus?.['inline']?.[step.id]?.complete) {\n continue\n }\n }\n if (step.condition && !step.condition({ job })) {\n continue\n }\n stepsToRun.push(step)\n }\n\n const tasks = getRunTaskFunction(job, workflowConfig, req, false, updateJob)\n const inlineTask = getRunTaskFunction(job, workflowConfig, req, true, updateJob)\n\n // Run the job\n try {\n await Promise.all(\n stepsToRun.map(async (step) => {\n if ('task' in step) {\n await tasks[step.task]!(step.id, {\n input: step.input ? step.input({ job }) : {},\n retries: step.retries,\n })\n } else {\n await inlineTask(step.id, {\n retries: step.retries,\n task: step.inlineTask as any, // TODO: Fix type\n })\n }\n }),\n )\n } catch (error) {\n const { hasFinalError } = await handleWorkflowError({\n error:\n error instanceof WorkflowError\n ? error\n : new WorkflowError({\n job,\n message:\n typeof error === 'object' && error && 'message' in error\n ? (error.message as string)\n : 'An unhandled error occurred',\n workflowConfig,\n }),\n silent,\n\n req,\n updateJob,\n })\n\n return {\n status: hasFinalError ? 'error-reached-max-retries' : 'error',\n }\n }\n\n // Check if workflow has completed\n let workflowCompleted = false\n for (const [slug, map] of Object.entries(job.taskStatus)) {\n for (const [id, taskStatus] of Object.entries(map)) {\n if (taskStatus.complete) {\n const step = workflowHandler.find((step) => {\n if ('task' in step) {\n return step.task === slug && step.id === id\n } else {\n return step.id === id && slug === 'inline'\n }\n })\n if (step?.completesJob) {\n workflowCompleted = true\n break\n }\n }\n }\n }\n\n if (workflowCompleted) {\n await updateJob({\n completedAt: getCurrentDate().toISOString(),\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n status: 'success',\n }\n } else {\n // Retry the job - no need to bump processing or totalTried as this does not count as a retry. A condition of a different task might have just opened up!\n return await runJSONJob({\n job,\n req,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n }\n}\n"],"names":["handleWorkflowError","WorkflowError","getCurrentDate","getRunTaskFunction","runJSONJob","job","req","silent","updateJob","workflowConfig","workflowHandler","stepsToRun","step","taskStatus","task","id","complete","condition","push","tasks","inlineTask","Promise","all","map","input","retries","error","hasFinalError","message","status","workflowCompleted","slug","Object","entries","find","completesJob","completedAt","toISOString","processing","totalTried"],"mappings":"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"}
|