From a217866cef6caaef9244f3d16d90f7027adc0c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 22 May 2024 15:22:07 +0200 Subject: [PATCH] fix(core): Account for retry of execution aborted by pre-execute hook (#9474) --- .../errors/aborted-execution-retry.error.ts | 9 ++++++ .../cli/src/executions/execution.service.ts | 3 ++ .../unit/services/execution.service.test.ts | 30 +++++++++++++++++++ .../src/plugins/i18n/locales/en.json | 2 +- 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 packages/cli/src/errors/aborted-execution-retry.error.ts create mode 100644 packages/cli/test/unit/services/execution.service.test.ts diff --git a/packages/cli/src/errors/aborted-execution-retry.error.ts b/packages/cli/src/errors/aborted-execution-retry.error.ts new file mode 100644 index 000000000..20d8b57e1 --- /dev/null +++ b/packages/cli/src/errors/aborted-execution-retry.error.ts @@ -0,0 +1,9 @@ +import { ApplicationError } from 'n8n-workflow'; + +export class AbortedExecutionRetryError extends ApplicationError { + constructor() { + super('The execution was aborted before starting, so it cannot be retried', { + level: 'warning', + }); + } +} diff --git a/packages/cli/src/executions/execution.service.ts b/packages/cli/src/executions/execution.service.ts index 2487dac2b..c245e2124 100644 --- a/packages/cli/src/executions/execution.service.ts +++ b/packages/cli/src/executions/execution.service.ts @@ -36,6 +36,7 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error'; import config from '@/config'; import { WaitTracker } from '@/WaitTracker'; import type { ExecutionEntity } from '@/databases/entities/ExecutionEntity'; +import { AbortedExecutionRetryError } from '@/errors/aborted-execution-retry.error'; export const schemaGetExecutionsQueryFilter = { $id: '/IGetExecutionsQueryFilter', @@ -129,6 +130,8 @@ export class ExecutionService { throw new NotFoundError(`The execution with the ID "${executionId}" does not exist.`); } + if (!execution.data.executionData) throw new AbortedExecutionRetryError(); + if (execution.finished) { throw new ApplicationError('The execution succeeded, so it cannot be retried.'); } diff --git a/packages/cli/test/unit/services/execution.service.test.ts b/packages/cli/test/unit/services/execution.service.test.ts new file mode 100644 index 000000000..e607fe0b6 --- /dev/null +++ b/packages/cli/test/unit/services/execution.service.test.ts @@ -0,0 +1,30 @@ +import type { IExecutionResponse } from '@/Interfaces'; +import type { ExecutionRepository } from '@/databases/repositories/execution.repository'; +import { AbortedExecutionRetryError } from '@/errors/aborted-execution-retry.error'; +import { ExecutionService } from '@/executions/execution.service'; +import type { ExecutionRequest } from '@/executions/execution.types'; +import { mock } from 'jest-mock-extended'; + +describe('ExecutionService', () => { + const executionRepository = mock(); + const executionService = new ExecutionService( + mock(), + mock(), + mock(), + executionRepository, + mock(), + mock(), + mock(), + mock(), + ); + + it('should error on retrying an aborted execution', async () => { + const abortedExecutionData = mock({ data: { executionData: undefined } }); + executionRepository.findWithUnflattenedData.mockResolvedValue(abortedExecutionData); + const req = mock(); + + const retry = executionService.retry(req, []); + + await expect(retry).rejects.toThrow(AbortedExecutionRetryError); + }); +}); diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 6ebd2b208..023c8398d 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -1218,7 +1218,7 @@ "nodeView.runButtonText.executeWorkflow": "Test workflow", "nodeView.runButtonText.executingWorkflow": "Executing workflow", "nodeView.runButtonText.waitingForTriggerEvent": "Waiting for trigger event", - "nodeView.showError.workflowError": "Workflow execution finished with an error", + "nodeView.showError.workflowError": "Workflow execution had an error", "nodeView.showError.getWorkflowDataFromUrl.title": "Problem loading workflow", "nodeView.showError.importWorkflowData.title": "Problem importing workflow", "nodeView.showError.mounted1.message": "There was a problem loading init data",