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

@@ -22,6 +22,7 @@ import { MessageEventBusDestinationWebhook } from '@/eventbus/MessageEventBusDes
import { MessageEventBusDestinationSentry } from '@/eventbus/MessageEventBusDestination/MessageEventBusDestinationSentry.ee';
import { EventMessageAudit } from '@/eventbus/EventMessageClasses/EventMessageAudit';
import { v4 as uuid } from 'uuid';
import { EventNamesTypes } from '../../src/eventbus/EventMessageClasses';
jest.unmock('@/eventbus/MessageEventBus/MessageEventBus');
jest.mock('axios');
@@ -62,12 +63,6 @@ const testSentryDestination: MessageEventBusDestinationSentryOptions = {
subscribedEvents: ['n8n.test.message', 'n8n.audit.user.updated'],
};
async function cleanLogs() {
eventBus.logWriter.cleanAllLogs();
const allMessages = await eventBus.getEventsAll();
expect(allMessages.length).toBe(0);
}
async function confirmIdInAll(id: string) {
const sent = await eventBus.getEventsAll();
expect(sent.length).toBeGreaterThan(0);
@@ -106,13 +101,13 @@ beforeAll(async () => {
config.set('eventBus.logWriter.logBaseName', 'n8n-test-logwriter');
config.set('eventBus.logWriter.keepLogCount', '1');
config.set('enterprise.features.logStreaming', true);
await eventBus.initialize();
});
beforeEach(async () => {
config.set('userManagement.disabled', false);
config.set('userManagement.isInstanceOwnerSetUp', true);
config.set('enterprise.features.logStreaming', false);
});
afterAll(async () => {
@@ -127,7 +122,10 @@ test('should have a running logwriter process', () => {
});
test('should have logwriter log messages', async () => {
const testMessage = new EventMessageGeneric({ eventName: 'n8n.test.message', id: uuid() });
const testMessage = new EventMessageGeneric({
eventName: 'n8n.test.message' as EventNamesTypes,
id: uuid(),
});
await eventBus.send(testMessage);
await new Promise((resolve) => {
eventBus.logWriter.worker?.once('message', async (msg: { command: string; data: any }) => {
@@ -176,10 +174,13 @@ test('GET /eventbus/destination all returned destinations should exist in eventb
}
});
// this test (presumably the mocking) is causing the test suite to randomly fail
test.skip('should send message to syslog', async () => {
const testMessage = new EventMessageGeneric({ eventName: 'n8n.test.message', id: uuid() });
const testMessage = new EventMessageGeneric({
eventName: 'n8n.test.message' as EventNamesTypes,
id: uuid(),
});
config.set('enterprise.features.logStreaming', true);
// await cleanLogs();
const syslogDestination = eventBus.destinations[
testSyslogDestination.id!
@@ -217,11 +218,10 @@ test.skip('should send message to syslog', async () => {
test.skip('should confirm send message if there are no subscribers', async () => {
const testMessageUnsubscribed = new EventMessageGeneric({
eventName: 'n8n.test.unsub',
eventName: 'n8n.test.unsub' as EventNamesTypes,
id: uuid(),
});
config.set('enterprise.features.logStreaming', true);
// await cleanLogs();
const syslogDestination = eventBus.destinations[
testSyslogDestination.id!
@@ -229,11 +229,6 @@ test.skip('should confirm send message if there are no subscribers', async () =>
syslogDestination.enable();
const mockedSyslogClientLog = jest.spyOn(syslogDestination.client, 'log');
mockedSyslogClientLog.mockImplementation((_m, _options, _cb) => {
return syslogDestination.client;
});
await eventBus.send(testMessageUnsubscribed);
await new Promise((resolve) => {
@@ -244,7 +239,6 @@ test.skip('should confirm send message if there are no subscribers', async () =>
await confirmIdInAll(testMessageUnsubscribed.id);
} else if (msg.command === 'confirmMessageSent') {
await confirmIdSent(testMessageUnsubscribed.id);
expect(mockedSyslogClientLog).toHaveBeenCalled();
syslogDestination.disable();
eventBus.logWriter.worker?.removeListener('message', handler002);
resolve(true);
@@ -264,7 +258,6 @@ test('should anonymize audit message to syslog ', async () => {
id: uuid(),
});
config.set('enterprise.features.logStreaming', true);
// await cleanLogs();
const syslogDestination = eventBus.destinations[
testSyslogDestination.id!
@@ -322,9 +315,11 @@ test('should anonymize audit message to syslog ', async () => {
});
test('should send message to webhook ', async () => {
const testMessage = new EventMessageGeneric({ eventName: 'n8n.test.message', id: uuid() });
const testMessage = new EventMessageGeneric({
eventName: 'n8n.test.message' as EventNamesTypes,
id: uuid(),
});
config.set('enterprise.features.logStreaming', true);
// await cleanLogs();
const webhookDestination = eventBus.destinations[
testWebhookDestination.id!
@@ -355,9 +350,11 @@ test('should send message to webhook ', async () => {
});
test('should send message to sentry ', async () => {
const testMessage = new EventMessageGeneric({ eventName: 'n8n.test.message', id: uuid() });
const testMessage = new EventMessageGeneric({
eventName: 'n8n.test.message' as EventNamesTypes,
id: uuid(),
});
config.set('enterprise.features.logStreaming', true);
// await cleanLogs();
const sentryDestination = eventBus.destinations[
testSentryDestination.id!