fix(core): Remove binary data when deleting executions by filter (#9056)

This commit is contained in:
Iván Ovejero 2024-04-05 18:00:35 +02:00 committed by GitHub
parent 0c90c7c8c1
commit 7bf0f900f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 37 additions and 6 deletions

View file

@ -407,7 +407,7 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
}
const query = this.createQueryBuilder('execution')
.select(['execution.id'])
.select(['execution.id', 'execution.workflowId'])
.andWhere('execution.workflowId IN (:...accessibleWorkflowIds)', { accessibleWorkflowIds });
if (deleteConditions.deleteBefore) {
@ -433,12 +433,19 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
return;
}
const executionIds = executions.map(({ id }) => id);
const ids = executions.map(({ id, workflowId }) => ({
executionId: id,
workflowId,
}));
do {
// Delete in batches to avoid "SQLITE_ERROR: Expression tree is too large (maximum depth 1000)" error
const batch = executionIds.splice(0, this.hardDeletionBatchSize);
await this.delete(batch);
} while (executionIds.length > 0);
const batch = ids.splice(0, this.hardDeletionBatchSize);
await Promise.all([
this.delete(batch.map(({ executionId }) => executionId)),
this.binaryDataService.deleteMany(batch),
]);
} while (ids.length > 0);
}
async getIdsSince(date: Date) {

View file

@ -1,14 +1,20 @@
import Container from 'typedi';
import type { SelectQueryBuilder } from '@n8n/typeorm';
import { Not, LessThanOrEqual } from '@n8n/typeorm';
import config from '@/config';
import { ExecutionEntity } from '@db/entities/ExecutionEntity';
import { ExecutionRepository } from '@db/repositories/execution.repository';
import { mockEntityManager } from '../../shared/mocking';
import { mockInstance } from '../../shared/mocking';
import { BinaryDataService } from 'n8n-core';
import { nanoid } from 'nanoid';
import { mock } from 'jest-mock-extended';
describe('ExecutionRepository', () => {
const entityManager = mockEntityManager(ExecutionEntity);
const binaryDataService = mockInstance(BinaryDataService);
const executionRepository = Container.get(ExecutionRepository);
const mockDate = new Date('2023-12-28 12:34:56.789Z');
@ -43,4 +49,22 @@ describe('ExecutionRepository', () => {
},
);
});
describe('deleteExecutionsByFilter', () => {
test('should delete binary data', async () => {
const workflowId = nanoid();
jest.spyOn(executionRepository, 'createQueryBuilder').mockReturnValue(
mock<SelectQueryBuilder<ExecutionEntity>>({
select: jest.fn().mockReturnThis(),
andWhere: jest.fn().mockReturnThis(),
getMany: jest.fn().mockResolvedValue([{ id: '1', workflowId }]),
}),
);
await executionRepository.deleteExecutionsByFilter({ id: '1' }, ['1'], { ids: ['1'] });
expect(binaryDataService.deleteMany).toHaveBeenCalledWith([{ executionId: '1', workflowId }]);
});
});
});