mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make runnable give friendly error about incorrect hierarchy for easier debugging
Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
aa32655cbe
commit
8aaf288ba6
@ -5,6 +5,8 @@
|
|||||||
import type { AsyncFnMock } from "@async-fn/jest";
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
import asyncFn from "@async-fn/jest";
|
import asyncFn from "@async-fn/jest";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createContainer,
|
createContainer,
|
||||||
getInjectable,
|
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<Runnable>({
|
||||||
|
id: "some-injection-token",
|
||||||
|
});
|
||||||
|
|
||||||
|
const someOtherInjectionToken = getInjectionToken<Runnable>({
|
||||||
|
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", () => {
|
describe("when running many with parameter", () => {
|
||||||
let runMock: AsyncFnMock<(...args: unknown[]) => Promise<void>>;
|
let runMock: AsyncFnMock<(...args: unknown[]) => Promise<void>>;
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import type {
|
|||||||
DiContainerForInjection,
|
DiContainerForInjection,
|
||||||
InjectionToken,
|
InjectionToken,
|
||||||
} from "@ogre-tools/injectable";
|
} 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<TParameter = void> {
|
export interface Runnable<TParameter = void> {
|
||||||
run: Run<TParameter>;
|
run: Run<TParameter>;
|
||||||
@ -24,12 +25,16 @@ export function runManyFor(di: DiContainerForInjection): RunMany {
|
|||||||
return (injectionToken) => async (parameter) => {
|
return (injectionToken) => async (parameter) => {
|
||||||
const allRunnables = di.injectMany(injectionToken);
|
const allRunnables = di.injectMany(injectionToken);
|
||||||
|
|
||||||
|
const throwWithIncorrectHierarchy = throwWithIncorrectHierarchyFor(allRunnables);
|
||||||
|
|
||||||
const recursedRun = async (
|
const recursedRun = async (
|
||||||
runAfterRunnable: Runnable<any> | undefined = undefined,
|
runAfterRunnable: Runnable<any> | undefined = undefined,
|
||||||
) =>
|
) =>
|
||||||
await pipeline(
|
await pipeline(
|
||||||
allRunnables,
|
allRunnables,
|
||||||
|
|
||||||
|
tap(runnables => forEach(throwWithIncorrectHierarchy, runnables)),
|
||||||
|
|
||||||
filter((runnable) => runnable.runAfter === runAfterRunnable),
|
filter((runnable) => runnable.runAfter === runAfterRunnable),
|
||||||
|
|
||||||
map(async (runnable) => {
|
map(async (runnable) => {
|
||||||
|
|||||||
@ -104,6 +104,51 @@ describe("runManySyncFor", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("given invalid hierarchy, when running runnables, throws", () => {
|
||||||
|
const rootDi = createContainer();
|
||||||
|
|
||||||
|
const runMock = jest.fn();
|
||||||
|
|
||||||
|
const someInjectionToken = getInjectionToken<RunnableSync>({
|
||||||
|
id: "some-injection-token",
|
||||||
|
});
|
||||||
|
|
||||||
|
const someOtherInjectionToken = getInjectionToken<RunnableSync>({
|
||||||
|
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", () => {
|
describe("when running many with parameter", () => {
|
||||||
let runMock: jest.Mock<(arg: string, arg2: string) => void>;
|
let runMock: jest.Mock<(arg: string, arg2: string) => void>;
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,9 @@ import type {
|
|||||||
DiContainerForInjection,
|
DiContainerForInjection,
|
||||||
InjectionToken,
|
InjectionToken,
|
||||||
} from "@ogre-tools/injectable";
|
} 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 type { Runnable } from "./run-many-for";
|
||||||
|
import { throwWithIncorrectHierarchyFor } from "./throw-with-incorrect-hierarchy-for";
|
||||||
|
|
||||||
export interface RunnableSync<TParameter = void> {
|
export interface RunnableSync<TParameter = void> {
|
||||||
run: RunSync<TParameter>;
|
run: RunSync<TParameter>;
|
||||||
@ -25,12 +26,16 @@ export function runManySyncFor(di: DiContainerForInjection): RunManySync {
|
|||||||
return (injectionToken) => async (parameter) => {
|
return (injectionToken) => async (parameter) => {
|
||||||
const allRunnables = di.injectMany(injectionToken);
|
const allRunnables = di.injectMany(injectionToken);
|
||||||
|
|
||||||
|
const throwWithIncorrectHierarchy = throwWithIncorrectHierarchyFor(allRunnables);
|
||||||
|
|
||||||
const recursedRun = (
|
const recursedRun = (
|
||||||
runAfterRunnable: RunnableSync<any> | undefined = undefined,
|
runAfterRunnable: RunnableSync<any> | undefined = undefined,
|
||||||
) =>
|
) =>
|
||||||
pipeline(
|
pipeline(
|
||||||
allRunnables,
|
allRunnables,
|
||||||
|
|
||||||
|
tap(runnables => forEach(throwWithIncorrectHierarchy, runnables)),
|
||||||
|
|
||||||
filter((runnable) => runnable.runAfter === runAfterRunnable),
|
filter((runnable) => runnable.runAfter === runAfterRunnable),
|
||||||
|
|
||||||
map((runnable) => {
|
map((runnable) => {
|
||||||
|
|||||||
16
src/common/runnable/throw-with-incorrect-hierarchy-for.ts
Normal file
16
src/common/runnable/throw-with-incorrect-hierarchy-for.ts
Normal file
@ -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<any>[] | RunnableSync<any>[]) =>
|
||||||
|
(runnable: Runnable<any> | RunnableSync<any>) => {
|
||||||
|
if (runnable.runAfter && !allRunnables.includes(runnable.runAfter)) {
|
||||||
|
throw new Error(
|
||||||
|
"Tried to run runnable after other runnable which does not same injection token.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user