From bbf6ec38bfa95a35b3380e12551571299918b959 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 1 Dec 2022 10:18:31 -0500 Subject: [PATCH] Fix runManyFor tests Signed-off-by: Sebastian Malton --- src/common/runnable/run-many-for.test.ts | 2 +- src/common/runnable/run-many-for.ts | 26 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/common/runnable/run-many-for.test.ts b/src/common/runnable/run-many-for.test.ts index c2cc152681..768eb57939 100644 --- a/src/common/runnable/run-many-for.test.ts +++ b/src/common/runnable/run-many-for.test.ts @@ -223,7 +223,7 @@ describe("runManyFor", () => { ); return expect(() => runMany()).rejects.toThrow( - /Tried to get a composite but encountered missing parent ids: "some-runnable-2".\n\nAvailable parent ids are:\n"[0-9a-z-]+",\n"some-runnable-1"/, + /Unreachable runnable="some-runnable-1". The specified runAfters; all of "some-runnable-2"; are not part of this injection token/, ); }); diff --git a/src/common/runnable/run-many-for.ts b/src/common/runnable/run-many-for.ts index 6f63160b4c..d5bff091eb 100644 --- a/src/common/runnable/run-many-for.ts +++ b/src/common/runnable/run-many-for.ts @@ -19,7 +19,8 @@ type Run = (parameter: Param) => Promise | void; export type RunMany = (injectionToken: InjectionToken, void>) => Run; -const computedNextEdge = (traversed: string[], graph: Map>, currentId: string) => { +const computedNextEdge = (traversed: string[], graph: Map>, currentId: string, seenIds: Set) => { + seenIds.add(currentId); const currentNode = graph.get(currentId); assert(currentNode, `Runnable graph does not contain node with id="${currentId}"`); @@ -29,13 +30,14 @@ const computedNextEdge = (traversed: string[], graph: Map>, throw new Error(`Cycle in runnable graph: "${traversed.join(`" -> "`)}" -> "${nextId}"`); } - computedNextEdge([...traversed, nextId], graph, nextId); + computedNextEdge([...traversed, nextId], graph, nextId, seenIds); } }; const verifyRunnablesAreDAG = (runnables: Runnable[]) => { const rootId = uuid.v4(); const runnableGraph = new Map>(); + const seenIds = new Set(); // Build the Directed graph for (const runnable of runnables) { @@ -52,8 +54,26 @@ const verifyRunnablesAreDAG = (runnables: Runnable[]) => { } } + getOrInsertSet(runnableGraph, rootId); + // Do a DFS to find any cycles - computedNextEdge([], runnableGraph, rootId); + computedNextEdge([], runnableGraph, rootId, seenIds); + + for (const id of runnableGraph.keys()) { + if (!seenIds.has(id)) { + const runnable = runnables.find(runnable => runnable.id === id); + + assert(runnable, `Unknown runnable id="${id}", logic error`); + + const runAfters = [runnable.runAfter] + .flat() + .filter(isDefined) + .map(runnable => runnable.id) + .join('", "'); + + throw new Error(`Unreachable runnable="${id}". The specified runAfters; all of "${runAfters}"; are not part of this injection token`); + } + } }; const executeRunnableWith = (param: Param) => {