diff --git a/packages/vlocity-deploy/src/__tests__/datapackDeployment.test.ts b/packages/vlocity-deploy/src/__tests__/datapackDeployment.test.ts index c12ce589..8f409a16 100644 --- a/packages/vlocity-deploy/src/__tests__/datapackDeployment.test.ts +++ b/packages/vlocity-deploy/src/__tests__/datapackDeployment.test.ts @@ -214,8 +214,8 @@ describe('DatapackDeployment', () => { }); }); - describe('isCircularDependencies', () => { - it('should return true when circular dependencies (A->B->A) exist', () => { + describe('hasCircularDependencies', () => { + it('should return path when circular dependencies (A->B->A) exist', () => { // Arrange const deployment = container.create(DatapackDeployment); const recordA = mockDatapackRecord( { sourceKey: 'A', datapackKey: 'A' }); @@ -227,10 +227,12 @@ describe('DatapackDeployment', () => { deployment.add(recordA, recordB); // Act - const result = deployment['isCircularDependencies'](recordA, recordB); + const result1 = deployment['hasCircularDependencies'](recordA); + const result2 = deployment['hasCircularDependencies'](recordB); // Assert - expect(result).toBe(true); + expect(result1).toStrictEqual([ 'A', 'B', 'A' ]); + expect(result2).toStrictEqual([ 'B', 'A', 'B' ]); }); it('should return true when a deep circular dependencies (A->B->C->A) exist', () => { // Arrange @@ -246,10 +248,10 @@ describe('DatapackDeployment', () => { deployment.add(recordA, recordB, recordC); // Act - const result = deployment['isCircularDependencies'](recordA, recordB); + const result = deployment['hasCircularDependencies'](recordA); // Assert - expect(result).toBe(true); + expect(result).toStrictEqual([ 'A', 'C', 'B', 'A' ]); }); }); }); \ No newline at end of file diff --git a/packages/vlocity-deploy/src/datapackDeployment.ts b/packages/vlocity-deploy/src/datapackDeployment.ts index 10375bb3..7cc35b6f 100644 --- a/packages/vlocity-deploy/src/datapackDeployment.ts +++ b/packages/vlocity-deploy/src/datapackDeployment.ts @@ -356,6 +356,10 @@ export class DatapackDeployment extends AsyncEventEmitter${dependentRecord.datapackKey}->${record.datapackKey}`); + continue; + } return true; } } @@ -372,6 +376,36 @@ export class DatapackDeployment extends AsyncEventEmitter()): boolean { + if (visited.has(datapackKeyB)) { + // Prevent a circular dependency check from going into an infinite loop + return false; + } else { + visited.add(datapackKeyB); + } + + for(const record of this.getRecords(datapackKeyB)) { + for (const dependency of record.getDependencies()) { + const dependentRecord = this.records.get(dependency.VlocityMatchingRecordSourceKey ?? dependency.VlocityLookupRecordSourceKey); + if (!dependentRecord || dependentRecord.datapackKey === datapackKeyB) { + continue; + } + if (dependentRecord.datapackKey === datapackKeyA) { + return true; + } else if (this.isCircularDatapackDependency(datapackKeyA, dependentRecord.datapackKey, visited)) { + return true; + } + } + } + return false; + } + private hasCircularDependencies(record: DatapackDeploymentRecord, graph = Array()): Array | false { if (!graph.length) { graph.push(record.sourceKey); @@ -379,7 +413,7 @@ export class DatapackDeployment extends AsyncEventEmitter