From 92f939f82799975a5f9b859e7f342f3440961320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Feb 2024 12:36:55 +0100 Subject: [PATCH] fix(core): Fix workflow tagging failure due to unique constraint check (#8505) --- .../workflowTagMapping.repository.ts | 10 +++ .../cli/src/workflows/workflow.service.ts | 5 +- ...tag-mapping.repository.integration.test.ts | 90 +++++++++++++++++++ 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 packages/cli/test/integration/workflow-tag-mapping.repository.integration.test.ts diff --git a/packages/cli/src/databases/repositories/workflowTagMapping.repository.ts b/packages/cli/src/databases/repositories/workflowTagMapping.repository.ts index c3a45e8624..c7184d711d 100644 --- a/packages/cli/src/databases/repositories/workflowTagMapping.repository.ts +++ b/packages/cli/src/databases/repositories/workflowTagMapping.repository.ts @@ -7,4 +7,14 @@ export class WorkflowTagMappingRepository extends Repository constructor(dataSource: DataSource) { super(WorkflowTagMapping, dataSource.manager); } + + async overwriteTaggings(workflowId: string, tagIds: string[]) { + return await this.manager.transaction(async () => { + await this.delete({ workflowId }); + + const taggings = tagIds.map((tagId) => this.create({ workflowId, tagId })); + + return await this.insert(taggings); + }); + } } diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index 3833510b75..56c19900ee 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -166,10 +166,7 @@ export class WorkflowService { ); if (tagIds && !config.getEnv('workflowTagsDisabled')) { - await this.workflowTagMappingRepository.delete({ workflowId }); - await this.workflowTagMappingRepository.insert( - tagIds.map((tagId) => ({ tagId, workflowId })), - ); + await this.workflowTagMappingRepository.overwriteTaggings(workflowId, tagIds); } if (workflow.versionId !== shared.workflow.versionId) { diff --git a/packages/cli/test/integration/workflow-tag-mapping.repository.integration.test.ts b/packages/cli/test/integration/workflow-tag-mapping.repository.integration.test.ts new file mode 100644 index 0000000000..7cf1dcdaed --- /dev/null +++ b/packages/cli/test/integration/workflow-tag-mapping.repository.integration.test.ts @@ -0,0 +1,90 @@ +import Container from 'typedi'; + +import * as testDb from './shared/testDb'; +import { WorkflowTagMappingRepository } from '@/databases/repositories/workflowTagMapping.repository'; +import { createWorkflow } from './shared/db/workflows'; +import { TagRepository } from '@/databases/repositories/tag.repository'; + +describe('WorkflowTagMappingRepository', () => { + let taggingRepository: WorkflowTagMappingRepository; + let tagRepository: TagRepository; + + beforeAll(async () => { + await testDb.init(); + + taggingRepository = Container.get(WorkflowTagMappingRepository); + tagRepository = Container.get(TagRepository); + }); + + afterEach(async () => { + await testDb.truncate(['WorkflowTagMapping', 'Workflow', 'Tag']); + }); + + afterAll(async () => { + await testDb.terminate(); + }); + + describe('overwriteTaggings', () => { + test('should overwrite taggings in a workflow', async () => { + const workflow = await createWorkflow(); + + const oldTags = await tagRepository.save( + ['tag1', 'tag2'].map((name) => tagRepository.create({ name })), + ); + + const oldTaggings = oldTags.map((tag) => + taggingRepository.create({ + tagId: tag.id, + workflowId: workflow.id, + }), + ); + + await taggingRepository.save(oldTaggings); + + const newTags = await tagRepository.save( + ['tag3', 'tag4'].map((name) => tagRepository.create({ name })), + ); + + await taggingRepository.overwriteTaggings( + workflow.id, + newTags.map((t) => t.id), + ); + + const taggings = await taggingRepository.findBy({ workflowId: workflow.id }); + + expect(taggings).toHaveLength(2); + + const [firstNewTag, secondNewTag] = newTags; + + expect(taggings).toEqual( + expect.arrayContaining([ + expect.objectContaining({ tagId: firstNewTag.id, workflowId: workflow.id }), + expect.objectContaining({ tagId: secondNewTag.id, workflowId: workflow.id }), + ]), + ); + }); + + test('should delete taggings if no tags are provided', async () => { + const workflow = await createWorkflow(); + + const oldTags = await tagRepository.save( + ['tag1', 'tag2'].map((name) => tagRepository.create({ name })), + ); + + const oldTaggings = oldTags.map((tag) => + taggingRepository.create({ + tagId: tag.id, + workflowId: workflow.id, + }), + ); + + await taggingRepository.save(oldTaggings); + + await taggingRepository.overwriteTaggings(workflow.id, []); + + const taggings = await taggingRepository.findBy({ workflowId: workflow.id }); + + expect(taggings).toHaveLength(0); + }); + }); +});