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
@@ -264,7 +264,7 @@ import {
|
||||
IExecutionsSummary,
|
||||
IWorkflowShortResponse,
|
||||
} from '@/Interface';
|
||||
import { IDataObject } from 'n8n-workflow';
|
||||
import type { ExecutionStatus, IDataObject } from 'n8n-workflow';
|
||||
import { range as _range } from 'lodash';
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { mapStores } from 'pinia';
|
||||
@@ -272,8 +272,6 @@ import { useUIStore } from '@/stores/ui';
|
||||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
import { setPageTitle } from '@/utils';
|
||||
|
||||
type ExecutionStatus = 'failed' | 'success' | 'waiting' | 'running' | 'unknown';
|
||||
|
||||
export default mixins(externalHooks, genericHelpers, executionHelpers, restApi, showMessage).extend(
|
||||
{
|
||||
name: 'ExecutionsList',
|
||||
@@ -337,6 +335,14 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
id: 'error',
|
||||
name: this.$locale.baseText('executionsList.error'),
|
||||
},
|
||||
{
|
||||
id: 'crashed',
|
||||
name: this.$locale.baseText('executionsList.error'),
|
||||
},
|
||||
{
|
||||
id: 'new',
|
||||
name: this.$locale.baseText('executionsList.new'),
|
||||
},
|
||||
{
|
||||
id: 'running',
|
||||
name: this.$locale.baseText('executionsList.running'),
|
||||
@@ -357,13 +363,12 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
combinedExecutions(): IExecutionsSummary[] {
|
||||
const returnData: IExecutionsSummary[] = [];
|
||||
|
||||
if (['ALL', 'running'].includes(this.filter.status)) {
|
||||
if (['ALL', 'running', 'new'].includes(this.filter.status)) {
|
||||
returnData.push(...this.activeExecutions);
|
||||
}
|
||||
if (['ALL', 'error', 'success', 'waiting'].includes(this.filter.status)) {
|
||||
if (['ALL', 'error', 'crashed', 'success', 'waiting'].includes(this.filter.status)) {
|
||||
returnData.push(...this.finishedExecutions);
|
||||
}
|
||||
|
||||
return returnData;
|
||||
},
|
||||
combinedExecutionsCount(): number {
|
||||
@@ -391,16 +396,31 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
return filter;
|
||||
},
|
||||
workflowFilterPast(): IDataObject {
|
||||
const filter: IDataObject = {};
|
||||
const queryFilter: IDataObject = {};
|
||||
if (this.filter.workflowId !== 'ALL') {
|
||||
filter.workflowId = this.filter.workflowId;
|
||||
queryFilter.workflowId = this.filter.workflowId;
|
||||
}
|
||||
if (this.filter.status === 'waiting') {
|
||||
filter.waitTill = true;
|
||||
} else if (['error', 'success'].includes(this.filter.status)) {
|
||||
filter.finished = this.filter.status === 'success';
|
||||
switch (this.filter.status as ExecutionStatus) {
|
||||
case 'waiting':
|
||||
queryFilter.status = ['waiting'];
|
||||
break;
|
||||
case 'crashed':
|
||||
queryFilter.status = ['crashed'];
|
||||
break;
|
||||
case 'new':
|
||||
queryFilter.status = ['new'];
|
||||
break;
|
||||
case 'error':
|
||||
queryFilter.status = ['failed', 'crashed', 'error'];
|
||||
break;
|
||||
case 'success':
|
||||
queryFilter.status = ['success'];
|
||||
break;
|
||||
case 'running':
|
||||
queryFilter.status = ['running'];
|
||||
break;
|
||||
}
|
||||
return filter;
|
||||
return queryFilter;
|
||||
},
|
||||
pageTitle() {
|
||||
return this.$locale.baseText('executionsList.workflowExecutions');
|
||||
@@ -793,19 +813,23 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
this.isDataLoading = false;
|
||||
},
|
||||
getStatus(execution: IExecutionsSummary): ExecutionStatus {
|
||||
let status: ExecutionStatus = 'unknown';
|
||||
if (execution.waitTill) {
|
||||
status = 'waiting';
|
||||
} else if (execution.stoppedAt === undefined) {
|
||||
status = 'running';
|
||||
} else if (execution.finished) {
|
||||
status = 'success';
|
||||
} else if (execution.stoppedAt !== null) {
|
||||
status = 'failed';
|
||||
} else {
|
||||
status = 'unknown';
|
||||
if (execution.status) return execution.status;
|
||||
else {
|
||||
// this should not happen but just in case
|
||||
let status: ExecutionStatus = 'unknown';
|
||||
if (execution.waitTill) {
|
||||
status = 'waiting';
|
||||
} else if (execution.stoppedAt === undefined) {
|
||||
status = 'running';
|
||||
} else if (execution.finished) {
|
||||
status = 'success';
|
||||
} else if (execution.stoppedAt !== null) {
|
||||
status = 'failed';
|
||||
} else {
|
||||
status = 'unknown';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
},
|
||||
getRowClass(execution: IExecutionsSummary): string {
|
||||
return [this.$style.execRow, this.$style[this.getStatus(execution)]].join(' ');
|
||||
@@ -816,6 +840,10 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
|
||||
if (status === 'waiting') {
|
||||
text = this.$locale.baseText('executionsList.waiting');
|
||||
} else if (status === 'crashed') {
|
||||
text = this.$locale.baseText('executionsList.error');
|
||||
} else if (status === 'new') {
|
||||
text = this.$locale.baseText('executionsList.new');
|
||||
} else if (status === 'running') {
|
||||
text = this.$locale.baseText('executionsList.running');
|
||||
} else if (status === 'success') {
|
||||
@@ -834,6 +862,10 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
|
||||
if (status === 'waiting') {
|
||||
path = 'executionsList.statusWaiting';
|
||||
} else if (status === 'crashed') {
|
||||
path = 'executionsList.statusText';
|
||||
} else if (status === 'new') {
|
||||
path = 'executionsList.statusNew';
|
||||
} else if (status === 'running') {
|
||||
path = 'executionsList.statusRunning';
|
||||
} else if (status === 'success') {
|
||||
@@ -990,6 +1022,10 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.crashed & {
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.waiting & {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
@@ -1099,6 +1135,10 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
|
||||
background: var(--color-danger);
|
||||
}
|
||||
|
||||
&.crashed td:first-child::before {
|
||||
background: var(--color-danger);
|
||||
}
|
||||
|
||||
&.success td:first-child::before {
|
||||
background: var(--color-success);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user