From 1d12a7fa7dac3c3dec660540ced0999c4c05acda Mon Sep 17 00:00:00 2001 From: Marley Powell Date: Thu, 17 Aug 2023 11:59:01 +0100 Subject: [PATCH] fix: :bug: updated `detectCircularDependency` in `DependencyGraph` to return circular dependencies starting from the first node Signed-off-by: Marley Powell --- .../src/lib/DependencyGraph.test.ts | 13 ++++++++++++- .../backend-app-api/src/lib/DependencyGraph.ts | 14 +++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/backend-app-api/src/lib/DependencyGraph.test.ts b/packages/backend-app-api/src/lib/DependencyGraph.test.ts index 65efac0252..0ac993484b 100644 --- a/packages/backend-app-api/src/lib/DependencyGraph.test.ts +++ b/packages/backend-app-api/src/lib/DependencyGraph.test.ts @@ -66,6 +66,17 @@ describe('DependencyGraph', () => { ).toEqual(['1', '2', '1']); }); + it('should detect a circular dep starting from the first node', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'], consumes: ['b'] }, + 2: { provides: ['b'], consumes: ['c'] }, + 3: { provides: ['c'], consumes: ['d'] }, + 4: { provides: ['d'], consumes: ['a'] }, + }).detectCircularDependency(), + ).toEqual(['1', '2', '3', '4', '1']); + }); + it('should detect a larger distant circular dep', async () => { expect( DependencyGraph.fromMap({ @@ -74,7 +85,7 @@ describe('DependencyGraph', () => { 3: { provides: ['c'], consumes: ['b'] }, 4: { provides: ['d', 'e'], consumes: ['c', 'a'] }, }).detectCircularDependency(), - ).toEqual(['2', '3', '4', '2']); + ).toEqual(['2', '4', '3', '2']); }); }); diff --git a/packages/backend-app-api/src/lib/DependencyGraph.ts b/packages/backend-app-api/src/lib/DependencyGraph.ts index 8fd679f555..3e7618a096 100644 --- a/packages/backend-app-api/src/lib/DependencyGraph.ts +++ b/packages/backend-app-api/src/lib/DependencyGraph.ts @@ -108,16 +108,16 @@ export class DependencyGraph { continue; } visited.add(node); - for (const produced of node.provides) { - const consumerNodes = this.#nodes.filter(other => - other.consumes.has(produced), + for (const consumed of node.consumes) { + const providerNodes = this.#nodes.filter(other => + other.provides.has(consumed), ); - for (const consumer of consumerNodes) { - if (consumer === startNode) { + for (const provider of providerNodes) { + if (provider === startNode) { return [...path, startNode.value]; } - if (!visited.has(consumer)) { - stack.push([consumer, [...path, consumer.value]]); + if (!visited.has(provider)) { + stack.push([provider, [...path, provider.value]]); } } }