fix: Add accurate concurrent executions count to executions list (#19249)

This commit is contained in:
Irénée
2025-09-15 13:23:05 +01:00
committed by GitHub
parent 7ded694ce7
commit dc75be3a6f
11 changed files with 225 additions and 62 deletions

View File

@@ -1,9 +1,11 @@
import { createTeamProject, createWorkflow, testDb } from '@n8n/backend-test-utils';
import { GlobalConfig } from '@n8n/config';
import type { ExecutionSummaries } from '@n8n/db';
import { ExecutionMetadataRepository, ExecutionRepository, WorkflowRepository } from '@n8n/db';
import { Container } from '@n8n/di';
import { mock } from 'jest-mock-extended';
import config from '@/config';
import { ExecutionService } from '@/executions/execution.service';
import { annotateExecution, createAnnotationTags, createExecution } from './shared/db/executions';
@@ -11,6 +13,7 @@ import { annotateExecution, createAnnotationTags, createExecution } from './shar
describe('ExecutionService', () => {
let executionService: ExecutionService;
let executionRepository: ExecutionRepository;
const globalConfig = Container.get(GlobalConfig);
beforeAll(async () => {
await testDb.init();
@@ -18,7 +21,7 @@ describe('ExecutionService', () => {
executionRepository = Container.get(ExecutionRepository);
executionService = new ExecutionService(
mock(),
globalConfig,
mock(),
mock(),
mock(),
@@ -34,6 +37,11 @@ describe('ExecutionService', () => {
);
});
beforeEach(() => {
globalConfig.executions.concurrency.productionLimit = -1;
config.set('executions.mode', 'regular');
});
afterEach(async () => {
await testDb.truncate(['ExecutionEntity']);
});
@@ -504,6 +512,67 @@ describe('ExecutionService', () => {
});
});
describe('getConcurrentExecutionsCount', () => {
test('should return concurrentExecutionsCount when concurrency is enabled', async () => {
globalConfig.executions.concurrency.productionLimit = 4;
const workflow = await createWorkflow();
const concurrentExecutionsData = await Promise.all([
createExecution({ status: 'running', mode: 'webhook' }, workflow),
createExecution({ status: 'running', mode: 'trigger' }, workflow),
]);
await Promise.all([
createExecution({ status: 'success' }, workflow),
createExecution({ status: 'crashed' }, workflow),
createExecution({ status: 'new' }, workflow),
createExecution({ status: 'running', mode: 'manual' }, workflow),
]);
const output = await executionService.getConcurrentExecutionsCount();
expect(output).toEqual(concurrentExecutionsData.length);
});
test('should set concurrentExecutionsCount to -1 when concurrency is disabled', async () => {
globalConfig.executions.concurrency.productionLimit = -1;
const workflow = await createWorkflow();
await Promise.all([
createExecution({ status: 'running', mode: 'webhook' }, workflow),
createExecution({ status: 'running', mode: 'trigger' }, workflow),
createExecution({ status: 'success' }, workflow),
createExecution({ status: 'crashed' }, workflow),
createExecution({ status: 'new' }, workflow),
createExecution({ status: 'running', mode: 'manual' }, workflow),
]);
const output = await executionService.getConcurrentExecutionsCount();
expect(output).toEqual(-1);
});
test('should set concurrentExecutionsCount to -1 in queue mode', async () => {
config.set('executions.mode', 'queue');
globalConfig.executions.concurrency.productionLimit = 4;
const workflow = await createWorkflow();
await Promise.all([
createExecution({ status: 'running', mode: 'webhook' }, workflow),
createExecution({ status: 'running', mode: 'trigger' }, workflow),
createExecution({ status: 'success' }, workflow),
createExecution({ status: 'crashed' }, workflow),
createExecution({ status: 'new' }, workflow),
createExecution({ status: 'running', mode: 'manual' }, workflow),
]);
const output = await executionService.getConcurrentExecutionsCount();
expect(output).toEqual(-1);
});
});
describe('findLatestCurrentAndCompleted', () => {
test('should return latest current and completed executions', async () => {
const workflow = await createWorkflow();