mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 12:57:29 -08:00
fix(core): Allow all executions to be stopped (#6386)
* allow all executions to be stopped and fix display issue * limit cancelation and add recover for unknown states
This commit is contained in:
parent
28bb797bb0
commit
cc44af9243
|
@ -1246,7 +1246,7 @@ export class Server extends AbstractServer {
|
||||||
throw new ResponseHelper.NotFoundError('Execution not found');
|
throw new ResponseHelper.NotFoundError('Execution not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const execution = await Db.collections.Execution.findOne({
|
const execution = await Db.collections.Execution.exist({
|
||||||
where: {
|
where: {
|
||||||
id: executionId,
|
id: executionId,
|
||||||
workflowId: In(sharedWorkflowIds),
|
workflowId: In(sharedWorkflowIds),
|
||||||
|
|
|
@ -18,11 +18,13 @@ import * as Db from '@/Db';
|
||||||
import * as ResponseHelper from '@/ResponseHelper';
|
import * as ResponseHelper from '@/ResponseHelper';
|
||||||
import type {
|
import type {
|
||||||
IExecutionFlattedDb,
|
IExecutionFlattedDb,
|
||||||
|
IExecutionResponse,
|
||||||
IExecutionsStopData,
|
IExecutionsStopData,
|
||||||
IWorkflowExecutionDataProcess,
|
IWorkflowExecutionDataProcess,
|
||||||
} from '@/Interfaces';
|
} from '@/Interfaces';
|
||||||
import { WorkflowRunner } from '@/WorkflowRunner';
|
import { WorkflowRunner } from '@/WorkflowRunner';
|
||||||
import { getWorkflowOwner } from '@/UserManagement/UserManagementHelper';
|
import { getWorkflowOwner } from '@/UserManagement/UserManagementHelper';
|
||||||
|
import { recoverExecutionDataFromEventLogMessages } from './eventbus/MessageEventBus/recoverEvents';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class WaitTracker {
|
export class WaitTracker {
|
||||||
|
@ -106,12 +108,29 @@ export class WaitTracker {
|
||||||
// Also check in database
|
// Also check in database
|
||||||
const execution = await Db.collections.Execution.findOneBy({ id: executionId });
|
const execution = await Db.collections.Execution.findOneBy({ id: executionId });
|
||||||
|
|
||||||
if (execution === null || !execution.waitTill) {
|
if (execution === null) {
|
||||||
throw new Error(`The execution ID "${executionId}" could not be found.`);
|
throw new Error(`The execution ID "${executionId}" could not be found.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullExecutionData = ResponseHelper.unflattenExecutionData(execution);
|
if (!['new', 'unknown', 'waiting', 'running'].includes(execution.status)) {
|
||||||
|
throw new Error(
|
||||||
|
`Only running or waiting executions can be stopped and ${executionId} is currently ${execution.status}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let fullExecutionData: IExecutionResponse;
|
||||||
|
try {
|
||||||
|
fullExecutionData = ResponseHelper.unflattenExecutionData(execution);
|
||||||
|
} catch (error) {
|
||||||
|
// if the execution ended in an unforseen, non-cancelable state, try to recover it
|
||||||
|
await recoverExecutionDataFromEventLogMessages(executionId, [], true);
|
||||||
|
// find recovered data
|
||||||
|
const recoveredExecution = await Db.collections.Execution.findOneBy({ id: executionId });
|
||||||
|
if (recoveredExecution) {
|
||||||
|
fullExecutionData = ResponseHelper.unflattenExecutionData(recoveredExecution);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Execution ${executionId} could not be recovered or canceled.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Set in execution in DB as failed and remove waitTill time
|
// Set in execution in DB as failed and remove waitTill time
|
||||||
const error = new WorkflowOperationError('Workflow-Execution has been canceled!');
|
const error = new WorkflowOperationError('Workflow-Execution has been canceled!');
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ export const executionHelpers = defineComponent({
|
||||||
if (execution.status === 'waiting' || execution.waitTill) {
|
if (execution.status === 'waiting' || execution.waitTill) {
|
||||||
status.name = 'waiting';
|
status.name = 'waiting';
|
||||||
status.label = this.$locale.baseText('executionsList.waiting');
|
status.label = this.$locale.baseText('executionsList.waiting');
|
||||||
|
} else if (execution.status === 'canceled') {
|
||||||
|
status.label = this.$locale.baseText('executionsList.canceled');
|
||||||
} else if (
|
} else if (
|
||||||
execution.status === 'running' ||
|
execution.status === 'running' ||
|
||||||
execution.status === 'new' ||
|
execution.status === 'new' ||
|
||||||
|
@ -57,8 +59,6 @@ export const executionHelpers = defineComponent({
|
||||||
} else if (execution.status === 'failed' || execution.status === 'crashed') {
|
} else if (execution.status === 'failed' || execution.status === 'crashed') {
|
||||||
status.name = 'error';
|
status.name = 'error';
|
||||||
status.label = this.$locale.baseText('executionsList.error');
|
status.label = this.$locale.baseText('executionsList.error');
|
||||||
} else if (execution.status === 'canceled') {
|
|
||||||
status.label = this.$locale.baseText('executionsList.canceled');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!execution.status) execution.status = 'unknown';
|
if (!execution.status) execution.status = 'unknown';
|
||||||
|
|
Loading…
Reference in a new issue