Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): Allow all executions to be stopped #6386

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@ export class Server extends AbstractServer {
throw new ResponseHelper.NotFoundError('Execution not found');
}

const execution = await Db.collections.Execution.findOne({
const execution = await Db.collections.Execution.exist({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest changing only this file.

Instead of making this change here revert the change to be findOne instead of exists.

Then, below, after the check for queue mode where we do const result = await this.activeExecutionsInstance.stopExecution(executionId); we can then have a check such as:

const result = await this.activeExecutionsInstance.stopExecution(executionId);
				let returnData: IExecutionsStopData;
				if (result === undefined) {
					if (['running', 'new'].includes(execution.status)) {
            // Do the stop procedure here as it's an execution that's not currently running but it's marked as running in DB
					} else {
					  // If active execution could not be found check if it is a waiting one
					  returnData = await this.waitTracker.stopExecution(executionId);
					}
				} else {
					returnData = {
						mode: result.mode,
						startedAt: new Date(result.startedAt),
						stoppedAt: result.stoppedAt ? new Date(result.stoppedAt) : undefined,
						finished: result.finished,
						status: result.status,
					};
				}

where: {
id: executionId,
workflowId: In(sharedWorkflowIds),
Expand Down
25 changes: 22 additions & 3 deletions packages/cli/src/WaitTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import * as Db from '@/Db';
import * as ResponseHelper from '@/ResponseHelper';
import type {
IExecutionFlattedDb,
IExecutionResponse,
IExecutionsStopData,
IWorkflowExecutionDataProcess,
} from '@/Interfaces';
import { WorkflowRunner } from '@/WorkflowRunner';
import { getWorkflowOwner } from '@/UserManagement/UserManagementHelper';
import { recoverExecutionDataFromEventLogMessages } from './eventbus/MessageEventBus/recoverEvents';

@Service()
export class WaitTracker {
Expand Down Expand Up @@ -106,12 +108,29 @@ export class WaitTracker {
// Also check in database
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.`);
}

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
const error = new WorkflowOperationError('Workflow-Execution has been canceled!');

Expand Down
4 changes: 2 additions & 2 deletions packages/editor-ui/src/mixins/executionsHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export const executionHelpers = defineComponent({
if (execution.status === 'waiting' || execution.waitTill) {
status.name = 'waiting';
status.label = this.$locale.baseText('executionsList.waiting');
} else if (execution.status === 'canceled') {
status.label = this.$locale.baseText('executionsList.canceled');
} else if (
execution.status === 'running' ||
execution.status === 'new' ||
Expand All @@ -57,8 +59,6 @@ export const executionHelpers = defineComponent({
} else if (execution.status === 'failed' || execution.status === 'crashed') {
status.name = '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';
Expand Down