1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Introduce a way to run many synchronous runnables

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-04-28 12:14:29 +03:00
parent 497c5258e6
commit d4b2ff992a
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
2 changed files with 194 additions and 0 deletions

View File

@ -0,0 +1,155 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import {
createContainer,
getInjectable,
getInjectionToken,
} from "@ogre-tools/injectable";
import type { RunnableSync } from "./run-many-sync-for";
import { runManySyncFor } from "./run-many-sync-for";
describe("runManySyncFor", () => {
describe("given hierarchy, when running many", () => {
let runMock: jest.Mock;
beforeEach(() => {
const rootDi = createContainer();
runMock = jest.fn();
const someInjectionTokenForRunnables = getInjectionToken<RunnableSync>({
id: "some-injection-token",
});
const someInjectable = getInjectable({
id: "some-injectable",
instantiate: () => ({ run: runMock }),
injectionToken: someInjectionTokenForRunnables,
});
const someOtherInjectable = getInjectable({
id: "some-other-injectable",
instantiate: () => ({ run: runMock }),
injectionToken: someInjectionTokenForRunnables,
});
rootDi.register(someInjectable, someOtherInjectable);
const runMany = runManySyncFor(rootDi)(someInjectionTokenForRunnables);
runMany();
});
it("runs all runnables at the same time", () => {
expect(runMock).toHaveBeenCalledTimes(2);
});
});
describe("given hierarchy that is three levels deep, when running many", () => {
let runMock: jest.Mock<(arg: string) => void>;
beforeEach(() => {
const di = createContainer();
runMock = jest.fn();
const someInjectionTokenForRunnables = getInjectionToken<RunnableSync>({
id: "some-injection-token",
});
const someInjectable1 = getInjectable({
id: "some-injectable-1",
instantiate: (di) => ({
run: () => runMock("third-level-run"),
runAfter: di.inject(someInjectable2),
}),
injectionToken: someInjectionTokenForRunnables,
});
const someInjectable2 = getInjectable({
id: "some-injectable-2",
instantiate: (di) => ({
run: () => runMock("second-level-run"),
runAfter: di.inject(someInjectable3),
}),
injectionToken: someInjectionTokenForRunnables,
});
const someInjectable3 = getInjectable({
id: "some-injectable-3",
instantiate: () => ({ run: () => runMock("first-level-run") }),
injectionToken: someInjectionTokenForRunnables,
});
di.register(someInjectable1, someInjectable2, someInjectable3);
const runMany = runManySyncFor(di)(someInjectionTokenForRunnables);
runMany();
});
it("runs runnables in order", () => {
expect(runMock.mock.calls).toEqual([["first-level-run"], ["second-level-run"], ["third-level-run"]]);
});
});
describe("when running many with parameter", () => {
let runMock: jest.Mock<(arg: string, arg2: string) => void>;
beforeEach(() => {
const rootDi = createContainer();
runMock = jest.fn();
const someInjectionTokenForRunnablesWithParameter = getInjectionToken<
RunnableSync<string>
>({
id: "some-injection-token",
});
const someInjectable = getInjectable({
id: "some-runnable-1",
instantiate: () => ({
run: (parameter) => runMock("run-of-some-runnable-1", parameter),
}),
injectionToken: someInjectionTokenForRunnablesWithParameter,
});
const someOtherInjectable = getInjectable({
id: "some-runnable-2",
instantiate: () => ({
run: (parameter) => runMock("run-of-some-runnable-2", parameter),
}),
injectionToken: someInjectionTokenForRunnablesWithParameter,
});
rootDi.register(someInjectable, someOtherInjectable);
const runMany = runManySyncFor(rootDi)(
someInjectionTokenForRunnablesWithParameter,
);
runMany("some-parameter");
});
it("runs all runnables using the parameter", () => {
expect(runMock.mock.calls).toEqual([
["run-of-some-runnable-1", "some-parameter"],
["run-of-some-runnable-2", "some-parameter"],
]);
});
});
});

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { pipeline } from "@ogre-tools/fp";
import type {
DiContainerForInjection,
InjectionToken,
} from "@ogre-tools/injectable";
import { filter, map } from "lodash/fp";
export interface RunnableSync<TParameter = void> {
run: (parameter: TParameter) => void;
runAfter?: this;
}
export const runManySyncFor =
(di: DiContainerForInjection) =>
<TRunnable extends RunnableSync<unknown>>(
injectionToken: InjectionToken<TRunnable, void>,
) =>
(parameter: Parameters<TRunnable["run"]>[0]) => {
const allRunnables = di.injectMany(injectionToken);
const recursedRun = (runAfterRunnable: RunnableSync<unknown> = undefined) =>
pipeline(
allRunnables,
filter((runnable) => runnable.runAfter === runAfterRunnable),
map((runnable) => {
runnable.run(parameter);
recursedRun(runnable);
}),
);
recursedRun();
};