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:
committed by
GitHub
parent
3a9c257f55
commit
d143f3f2ec
@@ -36,7 +36,7 @@ export interface MessageEventBusLogWriterOptions {
|
||||
interface ReadMessagesFromLogFileResult {
|
||||
loggedMessages: EventMessageTypes[];
|
||||
sentMessages: EventMessageTypes[];
|
||||
unfinishedExecutions: Set<string>;
|
||||
unfinishedExecutions: Record<string, EventMessageTypes[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +156,7 @@ export class MessageEventBusLogWriter {
|
||||
const results: ReadMessagesFromLogFileResult = {
|
||||
loggedMessages: [],
|
||||
sentMessages: [],
|
||||
unfinishedExecutions: new Set<string>(),
|
||||
unfinishedExecutions: {},
|
||||
};
|
||||
const logCount = logHistory
|
||||
? Math.min(config.get('eventBus.logWriter.keepLogCount') as number, logHistory)
|
||||
@@ -188,14 +188,28 @@ export class MessageEventBusLogWriter {
|
||||
if (isEventMessageOptions(json) && json.__type !== undefined) {
|
||||
const msg = getEventMessageObjectByType(json);
|
||||
if (msg !== null) results.loggedMessages.push(msg);
|
||||
if (msg?.eventName === 'n8n.workflow.started' && msg?.payload?.executionId) {
|
||||
results.unfinishedExecutions.add(msg?.payload?.executionId as string);
|
||||
} else if (
|
||||
(msg?.eventName === 'n8n.workflow.success' ||
|
||||
msg?.eventName === 'n8n.workflow.failed') &&
|
||||
msg?.payload?.executionId
|
||||
) {
|
||||
results.unfinishedExecutions.delete(msg?.payload?.executionId as string);
|
||||
if (msg?.eventName && msg.payload?.executionId) {
|
||||
const executionId = msg.payload.executionId as string;
|
||||
switch (msg.eventName) {
|
||||
case 'n8n.workflow.started':
|
||||
if (!Object.keys(results.unfinishedExecutions).includes(executionId)) {
|
||||
results.unfinishedExecutions[executionId] = [];
|
||||
}
|
||||
results.unfinishedExecutions[executionId] = [msg];
|
||||
break;
|
||||
case 'n8n.workflow.success':
|
||||
case 'n8n.workflow.failed':
|
||||
case 'n8n.workflow.crashed':
|
||||
delete results.unfinishedExecutions[executionId];
|
||||
break;
|
||||
case 'n8n.node.started':
|
||||
case 'n8n.node.finished':
|
||||
if (!Object.keys(results.unfinishedExecutions).includes(executionId)) {
|
||||
results.unfinishedExecutions[executionId] = [];
|
||||
}
|
||||
results.unfinishedExecutions[executionId].push(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isEventMessageConfirm(json) && mode !== 'all') {
|
||||
@@ -204,9 +218,10 @@ export class MessageEventBusLogWriter {
|
||||
results.sentMessages.push(...removedMessage);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
} catch (error) {
|
||||
LoggerProxy.error(
|
||||
`Error reading line messages from file: ${logFileName}, line: ${line}`,
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
`Error reading line messages from file: ${logFileName}, line: ${line}, ${error.message}}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -301,13 +316,13 @@ export class MessageEventBusLogWriter {
|
||||
return (await this.getMessages('unsent')).loggedMessages;
|
||||
}
|
||||
|
||||
async getUnfinishedExecutions(): Promise<Set<string>> {
|
||||
async getUnfinishedExecutions(): Promise<Record<string, EventMessageTypes[]>> {
|
||||
return (await this.getMessages('unfinished')).unfinishedExecutions;
|
||||
}
|
||||
|
||||
async getUnsentAndUnfinishedExecutions(): Promise<{
|
||||
unsentMessages: EventMessageTypes[];
|
||||
unfinishedExecutions: Set<string>;
|
||||
unfinishedExecutions: Record<string, EventMessageTypes[]>;
|
||||
}> {
|
||||
const result = await this.getMessages('unsent');
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user