diff --git a/src/common/runnable/run-many-for.test.ts b/src/common/runnable/run-many-for.test.ts index e281c6cb44..0783358d69 100644 --- a/src/common/runnable/run-many-for.test.ts +++ b/src/common/runnable/run-many-for.test.ts @@ -5,6 +5,8 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; + + import { createContainer, getInjectable, @@ -175,6 +177,51 @@ describe("runManyFor", () => { }); }); + it("given invalid hierarchy, when running runnables, throws", () => { + const rootDi = createContainer(); + + const runMock = asyncFn<(...args: unknown[]) => void>(); + + const someInjectionToken = getInjectionToken({ + id: "some-injection-token", + }); + + const someOtherInjectionToken = getInjectionToken({ + id: "some-other-injection-token", + }); + + const someInjectable = getInjectable({ + id: "some-runnable-1", + + instantiate: (di) => ({ + run: () => runMock("some-runnable-1"), + runAfter: di.inject(someOtherInjectable), + }), + + injectionToken: someInjectionToken, + }); + + const someOtherInjectable = getInjectable({ + id: "some-runnable-2", + + instantiate: () => ({ + run: () => runMock("some-runnable-2"), + }), + + injectionToken: someOtherInjectionToken, + }); + + rootDi.register(someInjectable, someOtherInjectable); + + const runMany = runManyFor(rootDi)( + someInjectionToken, + ); + + return expect(() => runMany()).rejects.toThrow( + "Tried to run runnable after other runnable which does not same injection token.", + ); + }); + describe("when running many with parameter", () => { let runMock: AsyncFnMock<(...args: unknown[]) => Promise>; diff --git a/src/common/runnable/run-many-for.ts b/src/common/runnable/run-many-for.ts index 93fd596810..f2c1a4ae56 100644 --- a/src/common/runnable/run-many-for.ts +++ b/src/common/runnable/run-many-for.ts @@ -7,7 +7,8 @@ import type { DiContainerForInjection, InjectionToken, } from "@ogre-tools/injectable"; -import { filter, map } from "lodash/fp"; +import { filter, forEach, map, tap } from "lodash/fp"; +import { throwWithIncorrectHierarchyFor } from "./throw-with-incorrect-hierarchy-for"; export interface Runnable { run: Run; @@ -24,12 +25,16 @@ export function runManyFor(di: DiContainerForInjection): RunMany { return (injectionToken) => async (parameter) => { const allRunnables = di.injectMany(injectionToken); + const throwWithIncorrectHierarchy = throwWithIncorrectHierarchyFor(allRunnables); + const recursedRun = async ( runAfterRunnable: Runnable | undefined = undefined, ) => await pipeline( allRunnables, + tap(runnables => forEach(throwWithIncorrectHierarchy, runnables)), + filter((runnable) => runnable.runAfter === runAfterRunnable), map(async (runnable) => { diff --git a/src/common/runnable/run-many-sync-for.test.ts b/src/common/runnable/run-many-sync-for.test.ts index 4e28362724..5a3ce32cb4 100644 --- a/src/common/runnable/run-many-sync-for.test.ts +++ b/src/common/runnable/run-many-sync-for.test.ts @@ -104,6 +104,51 @@ describe("runManySyncFor", () => { }); }); + it("given invalid hierarchy, when running runnables, throws", () => { + const rootDi = createContainer(); + + const runMock = jest.fn(); + + const someInjectionToken = getInjectionToken({ + id: "some-injection-token", + }); + + const someOtherInjectionToken = getInjectionToken({ + id: "some-other-injection-token", + }); + + const someInjectable = getInjectable({ + id: "some-runnable-1", + + instantiate: (di) => ({ + run: () => runMock("some-runnable-1"), + runAfter: di.inject(someOtherInjectable), + }), + + injectionToken: someInjectionToken, + }); + + const someOtherInjectable = getInjectable({ + id: "some-runnable-2", + + instantiate: () => ({ + run: () => runMock("some-runnable-2"), + }), + + injectionToken: someOtherInjectionToken, + }); + + rootDi.register(someInjectable, someOtherInjectable); + + const runMany = runManySyncFor(rootDi)( + someInjectionToken, + ); + + return expect(() => runMany()).rejects.toThrow( + "Tried to run runnable after other runnable which does not same injection token.", + ); + }); + describe("when running many with parameter", () => { let runMock: jest.Mock<(arg: string, arg2: string) => void>; diff --git a/src/common/runnable/run-many-sync-for.ts b/src/common/runnable/run-many-sync-for.ts index 32c2f608b0..cfe93fa4b3 100644 --- a/src/common/runnable/run-many-sync-for.ts +++ b/src/common/runnable/run-many-sync-for.ts @@ -7,8 +7,9 @@ import type { DiContainerForInjection, InjectionToken, } from "@ogre-tools/injectable"; -import { filter, map } from "lodash/fp"; +import { filter, forEach, map, tap } from "lodash/fp"; import type { Runnable } from "./run-many-for"; +import { throwWithIncorrectHierarchyFor } from "./throw-with-incorrect-hierarchy-for"; export interface RunnableSync { run: RunSync; @@ -25,12 +26,16 @@ export function runManySyncFor(di: DiContainerForInjection): RunManySync { return (injectionToken) => async (parameter) => { const allRunnables = di.injectMany(injectionToken); + const throwWithIncorrectHierarchy = throwWithIncorrectHierarchyFor(allRunnables); + const recursedRun = ( runAfterRunnable: RunnableSync | undefined = undefined, ) => pipeline( allRunnables, + tap(runnables => forEach(throwWithIncorrectHierarchy, runnables)), + filter((runnable) => runnable.runAfter === runAfterRunnable), map((runnable) => { diff --git a/src/common/runnable/throw-with-incorrect-hierarchy-for.ts b/src/common/runnable/throw-with-incorrect-hierarchy-for.ts new file mode 100644 index 0000000000..03073c4044 --- /dev/null +++ b/src/common/runnable/throw-with-incorrect-hierarchy-for.ts @@ -0,0 +1,16 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { Runnable } from "./run-many-for"; +import type { RunnableSync } from "./run-many-sync-for"; + +export const throwWithIncorrectHierarchyFor = + (allRunnables: Runnable[] | RunnableSync[]) => + (runnable: Runnable | RunnableSync) => { + if (runnable.runAfter && !allRunnables.includes(runnable.runAfter)) { + throw new Error( + "Tried to run runnable after other runnable which does not same injection token.", + ); + } + };