n8n/packages/cli/test/integration/executions/execution-persistence.test.ts
mfsiega b8b75719ba
feat(core): Warn and skip on duplicate scheduled executions (#28649)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:16:12 +00:00

73 lines
2.3 KiB
TypeScript

import { createWorkflow, testDb } from '@n8n/backend-test-utils';
import type { CreateExecutionPayload, WorkflowEntity } from '@n8n/db';
import { Container } from '@n8n/di';
import { createEmptyRunExecutionData } from 'n8n-workflow';
import { DuplicateExecutionError } from '@/errors/duplicate-execution.error';
import { ExecutionPersistence } from '@/executions/execution-persistence';
describe('ExecutionPersistence', () => {
let executionPersistence: ExecutionPersistence;
beforeAll(async () => {
await testDb.init();
executionPersistence = Container.get(ExecutionPersistence);
});
beforeEach(async () => {
await testDb.truncate(['ExecutionEntity']);
});
afterAll(async () => {
await testDb.terminate();
});
describe('create with deduplicationKey', () => {
const buildPayload = (
workflow: WorkflowEntity,
deduplicationKey?: string,
): CreateExecutionPayload => ({
data: createEmptyRunExecutionData(),
workflowData: workflow,
mode: 'trigger',
finished: false,
status: 'new',
workflowId: workflow.id,
deduplicationKey,
});
it('creates multiple executions when deduplicationKey is null', async () => {
const workflow = await createWorkflow();
const id1 = await executionPersistence.create(buildPayload(workflow));
const id2 = await executionPersistence.create(buildPayload(workflow));
const id3 = await executionPersistence.create(buildPayload(workflow));
expect(new Set([id1, id2, id3]).size).toBe(3);
});
it('creates executions with distinct deduplicationKeys', async () => {
const workflow = await createWorkflow();
const id1 = await executionPersistence.create(buildPayload(workflow, 'wf:node:t1'));
const id2 = await executionPersistence.create(buildPayload(workflow, 'wf:node:t2'));
expect(id1).not.toBe(id2);
});
it('throws DuplicateExecutionError when deduplicationKey is reused', async () => {
const workflow = await createWorkflow();
const key = 'wf:node:t1';
await executionPersistence.create(buildPayload(workflow, key));
await expect(executionPersistence.create(buildPayload(workflow, key))).rejects.toBeInstanceOf(
DuplicateExecutionError,
);
await expect(executionPersistence.create(buildPayload(workflow, key))).rejects.toMatchObject({
deduplicationKey: key,
});
});
});
});