UNPKG

payload

Version:

Node, React, Headless CMS and Application Framework built on Next.js

111 lines (110 loc) 4.4 kB
import ObjectIdImport from 'bson-objectid'; import { calculateBackoffWaitUntil } from './calculateBackoffWaitUntil.js'; import { getWorkflowRetryBehavior } from './getWorkflowRetryBehavior.js'; const ObjectId = ObjectIdImport.default || ObjectIdImport; export async function handleTaskError({ error, req, updateJob }) { const { executedAt, input, job, output, parent, retriesConfig, taskConfig, taskID, taskSlug, taskStatus, workflowConfig } = error.args; if (taskConfig?.onFail) { await taskConfig.onFail(); } const errorJSON = { name: error.name, cancelled: Boolean('cancelled' in error && error.cancelled), message: error.message, stack: error.stack }; const currentDate = new Date(); (job.log ??= []).push({ id: new ObjectId().toHexString(), completedAt: currentDate.toISOString(), error: errorJSON, executedAt: executedAt.toISOString(), input, output: output ?? {}, parent: req.payload.config.jobs.addParentToTaskLog ? parent : undefined, state: 'failed', taskID, taskSlug }); if (job.waitUntil) { // Check if waitUntil is in the past const waitUntil = new Date(job.waitUntil); if (waitUntil < currentDate) { // Outdated waitUntil, remove it delete job.waitUntil; } } let maxRetries = 0; if (retriesConfig?.attempts === undefined || retriesConfig?.attempts === null) { // Inherit retries from workflow config, if they are undefined and the workflow config has retries configured if (workflowConfig.retries !== undefined && workflowConfig.retries !== null) { maxRetries = typeof workflowConfig.retries === 'object' ? typeof workflowConfig.retries.attempts === 'number' ? workflowConfig.retries.attempts : 0 : workflowConfig.retries; } else { maxRetries = 0; } } else { maxRetries = retriesConfig.attempts; } if (!taskStatus?.complete && (taskStatus?.totalTried ?? 0) >= maxRetries) { /** * Task reached max retries => workflow will not retry */ await updateJob({ error: errorJSON, hasError: true, log: job.log, processing: false, totalTried: (job.totalTried ?? 0) + 1, waitUntil: job.waitUntil }); req.payload.logger.error({ err: error, job, msg: `Error running task ${taskID}. Attempt ${job.totalTried} - max retries reached`, taskSlug }); return { hasFinalError: true }; } /** * Task can retry: * - If workflow can retry, allow it to retry * - If workflow reached max retries, do not retry and set final error */ // First set task waitUntil - if the workflow waitUntil is later, it will be updated later const taskWaitUntil = calculateBackoffWaitUntil({ retriesConfig, totalTried: taskStatus?.totalTried ?? 0 }); // Update job's waitUntil only if this waitUntil is later than the current one if (!job.waitUntil || taskWaitUntil > new Date(job.waitUntil)) { job.waitUntil = taskWaitUntil.toISOString(); } const { hasFinalError, maxWorkflowRetries, waitUntil } = getWorkflowRetryBehavior({ job, retriesConfig: workflowConfig.retries }); req.payload.logger.error({ err: error, job, msg: `Error running task ${taskID}. Attempt ${job.totalTried + 1}${maxWorkflowRetries !== undefined ? '/' + (maxWorkflowRetries + 1) : ''}`, taskSlug }); // Update job's waitUntil only if this waitUntil is later than the current one if (waitUntil && (!job.waitUntil || waitUntil > new Date(job.waitUntil))) { job.waitUntil = waitUntil.toISOString(); } // 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) // we need to ensure the job is updated to reflect the error await updateJob({ error: hasFinalError ? errorJSON : undefined, hasError: hasFinalError, log: job.log, processing: false, totalTried: (job.totalTried ?? 0) + 1, waitUntil: job.waitUntil }); return { hasFinalError }; } //# sourceMappingURL=handleTaskError.js.map