From 5eb9c6728c7f1cde225c9cb85d7990ebb9c0f122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Thu, 11 Jul 2024 15:19:32 +0200 Subject: [PATCH] fix(core): Ensure executions cannot resume if already running --- packages/cli/src/WaitingWebhooks.ts | 4 + .../src/__tests__/waiting-webhooks.test.ts | 80 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 packages/cli/src/__tests__/waiting-webhooks.test.ts diff --git a/packages/cli/src/WaitingWebhooks.ts b/packages/cli/src/WaitingWebhooks.ts index ba3d6b4344ad9..d795c948f142f 100644 --- a/packages/cli/src/WaitingWebhooks.ts +++ b/packages/cli/src/WaitingWebhooks.ts @@ -57,6 +57,10 @@ export class WaitingWebhooks implements IWebhookManager { throw new NotFoundError(`The execution "${executionId} does not exist.`); } + if (execution.status === 'running') { + throw new ConflictError(`The execution "${executionId} is running already.`); + } + if (execution.finished || execution.data.resultData.error) { throw new ConflictError(`The execution "${executionId} has finished already.`); } diff --git a/packages/cli/src/__tests__/waiting-webhooks.test.ts b/packages/cli/src/__tests__/waiting-webhooks.test.ts new file mode 100644 index 0000000000000..6748c7233566f --- /dev/null +++ b/packages/cli/src/__tests__/waiting-webhooks.test.ts @@ -0,0 +1,80 @@ +import { mock } from 'jest-mock-extended'; +import { WaitingWebhooks } from '@/WaitingWebhooks'; +import { ConflictError } from '@/errors/response-errors/conflict.error'; +import { NotFoundError } from '@/errors/response-errors/not-found.error'; +import type { IExecutionResponse, WaitingWebhookRequest } from '@/Interfaces'; +import type express from 'express'; +import type { ExecutionRepository } from '@/databases/repositories/execution.repository'; + +describe('WaitingWebhooks', () => { + const executionRepository = mock(); + const waitingWebhooks = new WaitingWebhooks(mock(), mock(), executionRepository); + + beforeEach(() => { + jest.restoreAllMocks(); + }); + + it('should throw NotFoundError if there is no execution to resume', async () => { + /** + * Arrange + */ + executionRepository.findSingleExecution.mockResolvedValue(undefined); + + /** + * Act + */ + const promise = waitingWebhooks.executeWebhook( + mock(), + mock(), + ); + + /** + * Assert + */ + await expect(promise).rejects.toThrowError(NotFoundError); + }); + + it('should throw ConflictError if the execution to resume is already running', async () => { + /** + * Arrange + */ + executionRepository.findSingleExecution.mockResolvedValue( + mock({ status: 'running' }), + ); + + /** + * Act + */ + const promise = waitingWebhooks.executeWebhook( + mock(), + mock(), + ); + + /** + * Assert + */ + await expect(promise).rejects.toThrowError(ConflictError); + }); + + it('should throw ConflictError if the execution to resume already finished', async () => { + /** + * Arrange + */ + executionRepository.findSingleExecution.mockResolvedValue( + mock({ finished: true }), + ); + + /** + * Act + */ + const promise = waitingWebhooks.executeWebhook( + mock(), + mock(), + ); + + /** + * Assert + */ + await expect(promise).rejects.toThrowError(ConflictError); + }); +});