mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 08:34:07 -08:00
fix(core): Always save executions when they go into waiting state
This commit is contained in:
parent
565f8cd8c7
commit
314504c456
|
@ -1,5 +1,4 @@
|
||||||
import {
|
import {
|
||||||
deepCopy,
|
|
||||||
ErrorReporterProxy,
|
ErrorReporterProxy,
|
||||||
type IRunExecutionData,
|
type IRunExecutionData,
|
||||||
type ITaskData,
|
type ITaskData,
|
||||||
|
@ -87,37 +86,6 @@ test('should update execution when saving progress is enabled', async () => {
|
||||||
expect(reporterSpy).not.toHaveBeenCalled();
|
expect(reporterSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should update execution when saving progress is disabled, but waitTill is defined', async () => {
|
|
||||||
jest.spyOn(fnModule, 'toSaveSettings').mockReturnValue({
|
|
||||||
...commonSettings,
|
|
||||||
progress: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporterSpy = jest.spyOn(ErrorReporterProxy, 'error');
|
|
||||||
|
|
||||||
executionRepository.findSingleExecution.mockResolvedValue({} as IExecutionResponse);
|
|
||||||
|
|
||||||
const args = deepCopy(commonArgs);
|
|
||||||
args[4].waitTill = new Date();
|
|
||||||
await saveExecutionProgress(...args);
|
|
||||||
|
|
||||||
expect(executionRepository.updateExistingExecution).toHaveBeenCalledWith('some-execution-id', {
|
|
||||||
data: {
|
|
||||||
executionData: undefined,
|
|
||||||
resultData: {
|
|
||||||
lastNodeExecuted: 'My Node',
|
|
||||||
runData: {
|
|
||||||
'My Node': [{}],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
startData: {},
|
|
||||||
},
|
|
||||||
status: 'running',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(reporterSpy).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should report error on failure', async () => {
|
test('should report error on failure', async () => {
|
||||||
jest.spyOn(fnModule, 'toSaveSettings').mockReturnValue({
|
jest.spyOn(fnModule, 'toSaveSettings').mockReturnValue({
|
||||||
...commonSettings,
|
...commonSettings,
|
||||||
|
|
|
@ -16,7 +16,7 @@ export async function saveExecutionProgress(
|
||||||
) {
|
) {
|
||||||
const saveSettings = toSaveSettings(workflowData.settings);
|
const saveSettings = toSaveSettings(workflowData.settings);
|
||||||
|
|
||||||
if (!saveSettings.progress && !executionData.waitTill) return;
|
if (!saveSettings.progress) return;
|
||||||
|
|
||||||
const logger = Container.get(Logger);
|
const logger = Container.get(Logger);
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,20 @@ export function toSaveSettings(workflowSettings: IWorkflowSettings = {}) {
|
||||||
PROGRESS: config.getEnv('executions.saveExecutionProgress'),
|
PROGRESS: config.getEnv('executions.saveExecutionProgress'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
saveDataErrorExecution = DEFAULTS.ERROR,
|
||||||
|
saveDataSuccessExecution = DEFAULTS.SUCCESS,
|
||||||
|
saveManualExecutions = DEFAULTS.MANUAL,
|
||||||
|
saveExecutionProgress = DEFAULTS.PROGRESS,
|
||||||
|
} = workflowSettings;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
error: workflowSettings.saveDataErrorExecution
|
error: saveDataErrorExecution === 'DEFAULT' ? DEFAULTS.ERROR : saveDataErrorExecution === 'all',
|
||||||
? workflowSettings.saveDataErrorExecution !== 'none'
|
success:
|
||||||
: DEFAULTS.ERROR !== 'none',
|
saveDataSuccessExecution === 'DEFAULT'
|
||||||
success: workflowSettings.saveDataSuccessExecution
|
? DEFAULTS.SUCCESS
|
||||||
? workflowSettings.saveDataSuccessExecution !== 'none'
|
: saveDataSuccessExecution === 'all',
|
||||||
: DEFAULTS.SUCCESS !== 'none',
|
manual: saveManualExecutions === 'DEFAULT' ? DEFAULTS.MANUAL : saveManualExecutions,
|
||||||
manual:
|
progress: saveExecutionProgress === 'DEFAULT' ? DEFAULTS.PROGRESS : saveExecutionProgress,
|
||||||
workflowSettings === undefined || workflowSettings.saveManualExecutions === 'DEFAULT'
|
|
||||||
? DEFAULTS.MANUAL
|
|
||||||
: (workflowSettings.saveManualExecutions ?? DEFAULTS.MANUAL),
|
|
||||||
progress:
|
|
||||||
workflowSettings === undefined || workflowSettings.saveExecutionProgress === 'DEFAULT'
|
|
||||||
? DEFAULTS.PROGRESS
|
|
||||||
: (workflowSettings.saveExecutionProgress ?? DEFAULTS.PROGRESS),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,6 +464,11 @@ export async function executeWebhook(
|
||||||
projectId: project?.id,
|
projectId: project?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// When resuming from a wait node, copy over the pushRef from the execution-data
|
||||||
|
if (!runData.pushRef) {
|
||||||
|
runData.pushRef = runExecutionData.pushRef;
|
||||||
|
}
|
||||||
|
|
||||||
let responsePromise: IDeferredPromise<IN8nHttpFullResponse> | undefined;
|
let responsePromise: IDeferredPromise<IN8nHttpFullResponse> | undefined;
|
||||||
if (responseMode === 'responseNode') {
|
if (responseMode === 'responseNode') {
|
||||||
responsePromise = createDeferredPromise<IN8nHttpFullResponse>();
|
responsePromise = createDeferredPromise<IN8nHttpFullResponse>();
|
||||||
|
|
|
@ -448,7 +448,7 @@ function hookFunctionsSave(): IWorkflowExecuteHooks {
|
||||||
|
|
||||||
const saveSettings = toSaveSettings(this.workflowData.settings);
|
const saveSettings = toSaveSettings(this.workflowData.settings);
|
||||||
|
|
||||||
if (isManualMode && !saveSettings.manual && !fullRunData.waitTill) {
|
if (isManualMode && !saveSettings.manual && fullRunData.finished) {
|
||||||
/**
|
/**
|
||||||
* When manual executions are not being saved, we only soft-delete
|
* When manual executions are not being saved, we only soft-delete
|
||||||
* the execution so that the user can access its binary data
|
* the execution so that the user can access its binary data
|
||||||
|
@ -468,22 +468,21 @@ function hookFunctionsSave(): IWorkflowExecuteHooks {
|
||||||
(executionStatus === 'success' && !saveSettings.success) ||
|
(executionStatus === 'success' && !saveSettings.success) ||
|
||||||
(executionStatus !== 'success' && !saveSettings.error);
|
(executionStatus !== 'success' && !saveSettings.error);
|
||||||
|
|
||||||
if (shouldNotSave && !fullRunData.waitTill) {
|
if (shouldNotSave && fullRunData.finished && !isManualMode) {
|
||||||
if (!fullRunData.waitTill && !isManualMode) {
|
executeErrorWorkflow(
|
||||||
executeErrorWorkflow(
|
this.workflowData,
|
||||||
this.workflowData,
|
fullRunData,
|
||||||
fullRunData,
|
this.mode,
|
||||||
this.mode,
|
this.executionId,
|
||||||
this.executionId,
|
this.retryOf,
|
||||||
this.retryOf,
|
);
|
||||||
);
|
|
||||||
await Container.get(ExecutionRepository).hardDelete({
|
|
||||||
workflowId: this.workflowData.id,
|
|
||||||
executionId: this.executionId,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
await Container.get(ExecutionRepository).hardDelete({
|
||||||
}
|
workflowId: this.workflowData.id,
|
||||||
|
executionId: this.executionId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Although it is treated as IWorkflowBase here, it's being instantiated elsewhere with properties that may be sensitive
|
// Although it is treated as IWorkflowBase here, it's being instantiated elsewhere with properties that may be sensitive
|
||||||
|
@ -1117,6 +1116,9 @@ export function getWorkflowHooksWorkerMain(
|
||||||
hookFunctions.nodeExecuteAfter = [];
|
hookFunctions.nodeExecuteAfter = [];
|
||||||
hookFunctions.workflowExecuteAfter = [
|
hookFunctions.workflowExecuteAfter = [
|
||||||
async function (this: WorkflowHooks, fullRunData: IRun): Promise<void> {
|
async function (this: WorkflowHooks, fullRunData: IRun): Promise<void> {
|
||||||
|
// Don't delete executions before they are finished
|
||||||
|
if (!fullRunData.finished) return;
|
||||||
|
|
||||||
const executionStatus = determineFinalExecutionStatus(fullRunData);
|
const executionStatus = determineFinalExecutionStatus(fullRunData);
|
||||||
const saveSettings = toSaveSettings(this.workflowData.settings);
|
const saveSettings = toSaveSettings(this.workflowData.settings);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue