Skip to content

Commit

Permalink
[Presentation] Fix some bugs with services dependency injection (#126936
Browse files Browse the repository at this point in the history
)

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
Corey Robertson and kibanamachine authored Mar 7, 2022
1 parent c9e66b8 commit bc0d9e7
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ describe('DependencyManager', () => {
expect(DependencyManager.orderDependencies(graph)).toEqual(sortedTopology);
});

it('should include final vertex if it has dependencies', () => {
const graph = {
A: [],
B: [],
C: ['A', 'B'],
};
const sortedTopology = ['A', 'B', 'C'];
expect(DependencyManager.orderDependencies(graph)).toEqual(sortedTopology);
});

it('orderDependencies. Should return base topology if no depended vertices', () => {
const graph = {
N: [],
Expand All @@ -34,22 +44,34 @@ describe('DependencyManager', () => {
expect(DependencyManager.orderDependencies(graph)).toEqual(sortedTopology);
});

it('orderDependencies. Should detect circular dependencies and throw error with path', () => {
const graph = {
N: ['R'],
R: ['A'],
A: ['B'],
B: ['C'],
C: ['D'],
D: ['E'],
E: ['F'],
F: ['L'],
L: ['G'],
G: ['N'],
};
const circularPath = ['N', 'R', 'A', 'B', 'C', 'D', 'E', 'F', 'L', 'G', 'N'].join(' -> ');
const errorMessage = `Circular dependency detected while setting up services: ${circularPath}`;
describe('circular dependencies', () => {
it('should detect circular dependencies and throw error with path', () => {
const graph = {
N: ['R'],
R: ['A'],
A: ['B'],
B: ['C'],
C: ['D'],
D: ['E'],
E: ['F'],
F: ['L'],
L: ['G'],
G: ['N'],
};
const circularPath = ['G', 'L', 'F', 'E', 'D', 'C', 'B', 'A', 'R', 'N'].join(' -> ');
const errorMessage = `Circular dependency detected while setting up services: ${circularPath}`;

expect(() => DependencyManager.orderDependencies(graph)).toThrowError(errorMessage);
});

it('should detect circular dependency if circular reference is the first dependency for a vertex', () => {
const graph = {
A: ['B'],
B: ['A', 'C'],
C: [],
};

expect(() => DependencyManager.orderDependencies(graph)).toThrowError(errorMessage);
expect(() => DependencyManager.orderDependencies(graph)).toThrow();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ export class DependencyManager {
return cycleInfo;
}

return DependencyManager.sortVerticesFrom(srcVertex, graph, sortedVertices, {}, {});
return DependencyManager.sortVerticesFrom(
srcVertex,
graph,
sortedVertices,
{},
{},
cycleInfo
);
}, DependencyManager.createCycleInfo());
}

Expand All @@ -58,32 +65,41 @@ export class DependencyManager {
graph: Graph<T>,
sortedVertices: Set<T>,
visited: BreadCrumbs = {},
inpath: BreadCrumbs = {}
inpath: BreadCrumbs = {},
cycle: CycleDetectionResult<T>
): CycleDetectionResult<T> {
visited[srcVertex] = true;
inpath[srcVertex] = true;
const cycleInfo = graph[srcVertex]?.reduce<CycleDetectionResult<T> | undefined>(
(info, vertex) => {
if (inpath[vertex]) {
const path = (Object.keys(inpath) as T[]).filter(
(visitedVertex) => inpath[visitedVertex]
);
return DependencyManager.createCycleInfo([...path, vertex], true);
} else if (!visited[vertex]) {
return DependencyManager.sortVerticesFrom(vertex, graph, sortedVertices, visited, inpath);
}
return info;
},
undefined
);

const vertexEdges =
graph[srcVertex] === undefined || graph[srcVertex] === null ? [] : graph[srcVertex];

cycle = vertexEdges!.reduce<CycleDetectionResult<T>>((info, vertex) => {
if (inpath[vertex]) {
return { ...info, hasCycle: true };
} else if (!visited[vertex]) {
return DependencyManager.sortVerticesFrom(
vertex,
graph,
sortedVertices,
visited,
inpath,
info
);
}
return info;
}, cycle);

inpath[srcVertex] = false;

if (!sortedVertices.has(srcVertex)) {
sortedVertices.add(srcVertex);
}

return cycleInfo ?? DependencyManager.createCycleInfo<T>([...sortedVertices]);
return {
...cycle,
path: [...sortedVertices],
};
}

private static createCycleInfo<T extends GraphVertex = GraphVertex>(
Expand Down

0 comments on commit bc0d9e7

Please sign in to comment.