feat(core): Add execution runData recovery and status field (#5112)

* adds ExecutionEvents view modal to ExecutionList

* fix time rendering and remove wf column

* checks for unfinished executions and fails them

* prevent re-setting stoppedAt for execution

* some cleanup / manually create rundata after crash

* quicksave

* remove Threads lib, log worker rewrite

* cleanup comment

* fix sentry destination return value

* test for tests...

* run tests with single worker

* fix tests

* remove console log

* add endpoint for execution data recovery

* lint cleanup and some refactoring

* fix accidental recursion

* remove cyclic imports

* add rundata recovery to Workflowrunner

* remove comments

* cleanup and refactor

* adds a status field to executions

* setExecutionStatus on queued worker

* fix onWorkflowPostExecute

* set waiting from worker

* get crashed status into frontend

* remove comment

* merge fix

* cleanup

* catch empty rundata in recovery

* refactor IExecutionsSummary and inject nodeExecution Errors

* reduce default event log size to 10mb from 100mb

* add per node execution status

* lint fix

* merge and lint fix

* phrasing change

* improve preview rendering and messaging

* remove debug

* Improve partial rundata recovery

* fix labels

* fix line through

* send manual rundata to ui at crash

* some type and msg push fixes

* improve recovered item rendering in preview

* update workflowStatistics on recover

* merge fix

* review fixes

* merge fix

* notify eventbus when ui is back up

* add a small timeout to make sure the UI is back up

* increase reconnect timeout to 30s

* adjust recover timeout and ui connection lost msg

* do not stop execution in editor after x reconnects

* add executionRecovered push event

* fix recovered connection not green

* remove reconnect toast and  merge existing rundata

* merge editor and recovered data for own mode
This commit is contained in:
Michael Auerswald
2023-02-17 10:54:07 +01:00
committed by GitHub
parent 3a9c257f55
commit d143f3f2ec
71 changed files with 1245 additions and 307 deletions

View File

@@ -5,8 +5,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import type { IDeferredPromise, IExecuteResponsePromiseData, IRun } from 'n8n-workflow';
import { createDeferredPromise } from 'n8n-workflow';
import type {
IDeferredPromise,
IExecuteResponsePromiseData,
IRun,
ExecutionStatus,
} from 'n8n-workflow';
import { createDeferredPromise, LoggerProxy } from 'n8n-workflow';
import type { ChildProcess } from 'child_process';
import { stringify } from 'flatted';
@@ -36,6 +41,7 @@ export class ActiveExecutions {
process?: ChildProcess,
executionId?: string,
): Promise<string> {
let executionStatus: ExecutionStatus = executionId ? 'running' : 'new';
if (executionId === undefined) {
// Is a new execution so save in DB
@@ -45,6 +51,7 @@ export class ActiveExecutions {
finished: false,
startedAt: new Date(),
workflowData: executionData.workflowData,
status: executionStatus,
};
if (executionData.retryOf !== undefined) {
@@ -59,32 +66,37 @@ export class ActiveExecutions {
const execution = ResponseHelper.flattenExecutionData(fullExecutionData);
const executionResult = await Db.collections.Execution.save(execution as IExecutionFlattedDb);
// TODO: what is going on here?
executionId =
typeof executionResult.id === 'object'
? // @ts-ignore
executionResult.id!.toString()
: executionResult.id + '';
if (executionId === undefined) {
throw new Error('There was an issue assigning an execution id to the execution');
}
executionStatus = 'running';
} else {
// Is an existing execution we want to finish so update in DB
const execution = {
const execution: Pick<IExecutionFlattedDb, 'id' | 'data' | 'waitTill' | 'status'> = {
id: executionId,
data: stringify(executionData.executionData!),
waitTill: null,
status: executionStatus,
};
await Db.collections.Execution.update(executionId, execution);
}
// @ts-ignore
this.activeExecutions[executionId] = {
executionData,
process,
startedAt: new Date(),
postExecutePromises: [],
status: executionStatus,
};
// @ts-ignore
return executionId;
}
@@ -215,11 +227,31 @@ export class ActiveExecutions {
startedAt: data.startedAt,
mode: data.executionData.executionMode,
workflowId: data.executionData.workflowData.id! as string,
status: data.status,
});
}
return returnData;
}
async setStatus(executionId: string, status: ExecutionStatus): Promise<void> {
if (this.activeExecutions[executionId] === undefined) {
LoggerProxy.debug(
`There is no active execution with id "${executionId}", can't update status to ${status}.`,
);
return;
}
this.activeExecutions[executionId].status = status;
}
getStatus(executionId: string): ExecutionStatus {
if (this.activeExecutions[executionId] === undefined) {
return 'unknown';
}
return this.activeExecutions[executionId].status;
}
}
let activeExecutionsInstance: ActiveExecutions | undefined;