fix(core): Ensure failed executions are saved in queue mode (#7744)

This PR adds `status` to run data so that
`determineFinalExecutionStatus` resolves correctly on execution failure
and removes the cleanup that is being duplicated in a worker hook.

Followup to https://github.com/n8n-io/n8n/pull/7138

Should fix:
- https://github.com/n8n-io/n8n/issues/7705
-
https://linear.app/n8n/issue/PAY-964/no-execution-found-after-execution-fails
-
https://linear.app/n8n/issue/PAY-1010/execution-deletion-in-queue-mode-not-complying-with-settings
This commit is contained in:
Iván Ovejero 2023-11-20 16:03:02 +01:00 committed by GitHub
parent ad04986ce7
commit b7c5c7406f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 7 additions and 30 deletions

View file

@ -559,11 +559,8 @@ export class WorkflowRunner {
};
}
let racingPromisesResult: JobResponse = {
success: false,
};
try {
racingPromisesResult = await Promise.race(racingPromises);
await Promise.race(racingPromises);
if (clearWatchdogInterval !== undefined) {
clearWatchdogInterval();
}
@ -617,6 +614,7 @@ export class WorkflowRunner {
mode: fullExecutionData.mode,
startedAt: fullExecutionData.startedAt,
stoppedAt: fullExecutionData.stoppedAt,
status: fullExecutionData.status,
} as IRun;
if (executionHasPostExecutionPromises) {
@ -631,31 +629,6 @@ export class WorkflowRunner {
// Normally also static data should be supplied here but as it only used for sending
// data to editor-UI is not needed.
await hooks.executeHookFunctions('workflowExecuteAfter', [runData]);
try {
// Check if this execution data has to be removed from database
// based on workflow settings.
const workflowSettings = data.workflowData.settings ?? {};
const saveDataErrorExecution =
workflowSettings.saveDataErrorExecution ?? config.getEnv('executions.saveDataOnError');
const saveDataSuccessExecution =
workflowSettings.saveDataSuccessExecution ??
config.getEnv('executions.saveDataOnSuccess');
const workflowDidSucceed = !racingPromisesResult.error;
if (
(workflowDidSucceed && saveDataSuccessExecution === 'none') ||
(!workflowDidSucceed && saveDataErrorExecution === 'none')
) {
await Container.get(ExecutionRepository).hardDelete({
workflowId: data.workflowData.id as string,
executionId,
});
}
// eslint-disable-next-line id-denylist
} catch (err) {
// We don't want errors here to crash n8n. Just log and proceed.
console.log('Error removing saved execution from database. More details: ', err);
}
resolve(runData);
},

View file

@ -10,8 +10,12 @@ import { Logger } from '@/Logger';
export function determineFinalExecutionStatus(runData: IRun): ExecutionStatus {
const workflowHasCrashed = runData.status === 'crashed';
const workflowWasCanceled = runData.status === 'canceled';
const workflowHasFailed = runData.status === 'failed';
const workflowDidSucceed =
!runData.data.resultData?.error && !workflowHasCrashed && !workflowWasCanceled;
!runData.data.resultData?.error &&
!workflowHasCrashed &&
!workflowWasCanceled &&
!workflowHasFailed;
let workflowStatusFinal: ExecutionStatus = workflowDidSucceed ? 'success' : 'failed';
if (workflowHasCrashed) workflowStatusFinal = 'crashed';
if (workflowWasCanceled) workflowStatusFinal = 'canceled';