fix(core): Fix execution status filters (#5533)

* fix status filters

* fix countfilter

* add migrations to backfill status

* fix migrations
This commit is contained in:
Michael Auerswald 2023-02-21 21:44:46 +01:00 committed by GitHub
parent 52f740b9e8
commit 17eff4d7d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 135 additions and 1 deletions

View file

@ -225,6 +225,7 @@ export interface IExecutionsStopData {
mode: WorkflowExecuteMode;
startedAt: Date;
stoppedAt?: Date;
status: ExecutionStatus;
}
export interface IExecutionsCurrentSummary {

View file

@ -145,6 +145,7 @@ import { eventBus } from './eventbus';
import { isSamlEnabled } from './Saml/helpers';
import { Container } from 'typedi';
import { InternalHooks } from './InternalHooks';
import { getStatusUsingPreviousExecutionStatusMethod } from './executions/executionHelpers';
const exec = promisify(callbackExec);
@ -986,6 +987,9 @@ class Server extends AbstractServer {
if (!executions.length) return [];
return executions.map((execution) => {
if (!execution.status) {
execution.status = getStatusUsingPreviousExecutionStatusMethod(execution);
}
return {
id: execution.id,
workflowId: execution.workflowId,
@ -1020,6 +1024,7 @@ class Server extends AbstractServer {
mode: data.mode,
retryOf: data.retryOf,
startedAt: new Date(data.startedAt),
status: data.status,
});
}
@ -1072,6 +1077,7 @@ class Server extends AbstractServer {
startedAt: new Date(result.startedAt),
stoppedAt: result.stoppedAt ? new Date(result.stoppedAt) : undefined,
finished: result.finished,
status: result.status,
} as IExecutionsStopData;
}
@ -1098,6 +1104,7 @@ class Server extends AbstractServer {
? new Date(fullExecutionData.stoppedAt)
: undefined,
finished: fullExecutionData.finished,
status: fullExecutionData.status,
};
return returnData;
@ -1116,6 +1123,7 @@ class Server extends AbstractServer {
startedAt: new Date(result.startedAt),
stoppedAt: result.stoppedAt ? new Date(result.stoppedAt) : undefined,
finished: result.finished,
status: result.status,
};
}

View file

@ -144,6 +144,7 @@ export class WaitTracker {
startedAt: new Date(fullExecutionData.startedAt),
stoppedAt: fullExecutionData.stoppedAt ? new Date(fullExecutionData.stoppedAt) : undefined,
finished: fullExecutionData.finished,
status: fullExecutionData.status,
};
}

View file

@ -0,0 +1,28 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { logMigrationEnd, logMigrationStart } from '@db/utils/migrationHelpers';
import config from '@/config';
export class MigrateExecutionStatus1676996103000 implements MigrationInterface {
name = 'MigrateExecutionStatus1676996103000';
public async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
`UPDATE \`${tablePrefix}execution_entity\` SET status='waiting' WHERE status IS NULL AND \`waitTill\` IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE \`${tablePrefix}execution_entity\` SET status='failed' WHERE status IS NULL AND finished=0 AND \`stoppedAt\` IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE \`${tablePrefix}execution_entity\` SET status='success' WHERE status IS NULL AND finished=1 AND \`stoppedAt\` IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE \`${tablePrefix}execution_entity\` SET status='crashed' WHERE status IS NULL;`,
);
logMigrationEnd(this.name);
}
public async down(queryRunner: QueryRunner): Promise<void> {}
}

View file

@ -32,6 +32,7 @@ import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-Dele
import { CreateLdapEntities1674509946020 } from './1674509946020-CreateLdapEntities';
import { PurgeInvalidWorkflowConnections1675940580449 } from './1675940580449-PurgeInvalidWorkflowConnections';
import { AddStatusToExecutions1674138566000 } from './1674138566000-AddStatusToExecutions';
import { MigrateExecutionStatus1676996103000 } from './1676996103000-MigrateExecutionStatus';
export const mysqlMigrations = [
InitialMigration1588157391238,
@ -68,4 +69,5 @@ export const mysqlMigrations = [
CreateLdapEntities1674509946020,
PurgeInvalidWorkflowConnections1675940580449,
AddStatusToExecutions1674138566000,
MigrateExecutionStatus1676996103000,
];

View file

@ -0,0 +1,28 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { logMigrationEnd, logMigrationStart } from '@db/utils/migrationHelpers';
import config from '@/config';
export class MigrateExecutionStatus1676996103000 implements MigrationInterface {
name = 'MigrateExecutionStatus1676996103000';
public async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'waiting' WHERE "status" IS NULL AND "waitTill" IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'failed' WHERE "status" IS NULL AND "finished"=false AND "stoppedAt" IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'success' WHERE "status" IS NULL AND "finished"=true AND "stoppedAt" IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'crashed' WHERE "status" IS NULL;`,
);
logMigrationEnd(this.name);
}
public async down(queryRunner: QueryRunner): Promise<void> {}
}

View file

@ -30,6 +30,7 @@ import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-Dele
import { CreateLdapEntities1674509946020 } from './1674509946020-CreateLdapEntities';
import { PurgeInvalidWorkflowConnections1675940580449 } from './1675940580449-PurgeInvalidWorkflowConnections';
import { AddStatusToExecutions1674138566000 } from './1674138566000-AddStatusToExecutions';
import { MigrateExecutionStatus1676996103000 } from './1676996103000-MigrateExecutionStatus';
export const postgresMigrations = [
InitialMigration1587669153312,
@ -64,4 +65,5 @@ export const postgresMigrations = [
CreateLdapEntities1674509946020,
PurgeInvalidWorkflowConnections1675940580449,
AddStatusToExecutions1674138566000,
MigrateExecutionStatus1676996103000,
];

View file

@ -0,0 +1,28 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { logMigrationEnd, logMigrationStart } from '@db/utils/migrationHelpers';
import config from '@/config';
export class MigrateExecutionStatus1676996103000 implements MigrationInterface {
name = 'MigrateExecutionStatus1676996103000';
public async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'waiting' WHERE "status" IS NULL AND "waitTill" IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'failed' WHERE "status" IS NULL AND "finished"=0 AND "stoppedAt" IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'success' WHERE "status" IS NULL AND "finished"=1 AND "stoppedAt" IS NOT NULL;`,
);
await queryRunner.query(
`UPDATE "${tablePrefix}execution_entity" SET "status" = 'crashed' WHERE "status" IS NULL;`,
);
logMigrationEnd(this.name);
}
public async down(queryRunner: QueryRunner): Promise<void> {}
}

View file

@ -29,6 +29,7 @@ import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-Dele
import { CreateLdapEntities1674509946020 } from './1674509946020-CreateLdapEntities';
import { PurgeInvalidWorkflowConnections1675940580449 } from './1675940580449-PurgeInvalidWorkflowConnections';
import { AddStatusToExecutions1674138566000 } from './1674138566000-AddStatusToExecutions';
import { MigrateExecutionStatus1676996103000 } from './1676996103000-MigrateExecutionStatus';
const sqliteMigrations = [
InitialMigration1588102412422,
@ -62,6 +63,7 @@ const sqliteMigrations = [
CreateLdapEntities1674509946020,
PurgeInvalidWorkflowConnections1675940580449,
AddStatusToExecutions1674138566000,
MigrateExecutionStatus1676996103000,
];
export { sqliteMigrations };

View file

@ -0,0 +1,18 @@
import type { IExecutionFlattedDb } from '../Interfaces';
import type { ExecutionStatus } from 'n8n-workflow';
export function getStatusUsingPreviousExecutionStatusMethod(
execution: IExecutionFlattedDb,
): ExecutionStatus {
if (execution.waitTill) {
return 'waiting';
} else if (execution.stoppedAt === undefined) {
return 'running';
} else if (execution.finished) {
return 'success';
} else if (execution.stoppedAt !== null) {
return 'failed';
} else {
return 'unknown';
}
}

View file

@ -35,6 +35,7 @@ import * as Db from '@/Db';
import * as GenericHelpers from '@/GenericHelpers';
import { parse } from 'flatted';
import { Container } from 'typedi';
import { getStatusUsingPreviousExecutionStatusMethod } from './executionHelpers';
interface IGetExecutionsQueryFilter {
id?: FindOperator<string>;
@ -213,7 +214,6 @@ export class ExecutionsService {
};
if (filter?.status) {
Object.assign(findWhere, { status: In(filter.status) });
delete filter.status; // remove status from filter so it does not get applied twice
}
if (filter?.finished) {
Object.assign(findWhere, { finished: filter.finished });
@ -259,12 +259,18 @@ export class ExecutionsService {
'execution.startedAt',
'execution.stoppedAt',
'execution.workflowData',
'execution.status',
])
.orderBy('id', 'DESC')
.take(limit)
.where(findWhere);
const countFilter = deepCopy(filter ?? {});
// deepcopy breaks the In operator so we need to reapply it
if (filter?.status) {
Object.assign(filter, { status: In(filter.status) });
Object.assign(countFilter, { status: In(filter.status) });
}
if (filter) {
this.massageFilters(filter as IDataObject);
@ -286,6 +292,10 @@ export class ExecutionsService {
const nodeExecutionStatus = {};
let lastNodeExecuted;
let executionError;
// fill execution status for old executions that will return null
if (!execution.status) {
execution.status = getStatusUsingPreviousExecutionStatusMethod(execution);
}
try {
const data = parse(execution.data) as IRunExecutionData;
lastNodeExecuted = data?.resultData?.lastNodeExecuted ?? '';
@ -363,6 +373,10 @@ export class ExecutionsService {
return undefined;
}
if (!execution.status) {
execution.status = getStatusUsingPreviousExecutionStatusMethod(execution);
}
if (req.query.unflattedResponse === 'true') {
return ResponseHelper.unflattenExecutionData(execution);
}

View file

@ -31,6 +31,7 @@ import {
IExecutionsSummary,
IAbstractEventMessage,
FeatureFlags,
ExecutionStatus,
} from 'n8n-workflow';
import { SignInType } from './constants';
import { FAKE_DOOR_FEATURES, TRIGGER_NODE_FILTER, REGULAR_NODE_FILTER } from './constants';
@ -383,6 +384,7 @@ export interface IExecutionsStopData {
mode: WorkflowExecuteMode;
startedAt: Date;
stoppedAt: Date;
status: ExecutionStatus;
}
export interface IExecutionDeleteFilter {