mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
/**
|
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
*/
|
|
import type { DiContainerForInjection, InjectionToken } from "@ogre-tools/injectable";
|
|
import { getOrInsert } from "@k8slens/utilities";
|
|
import type TypedEventEmitter from "typed-emitter";
|
|
import EventEmitter from "events";
|
|
import { convertToWithIdWith, verifyRunnablesAreDAG } from "./helpers";
|
|
import type { RunnableWithId, Runnable, Run } from "./types";
|
|
import type { Asyncify } from "type-fest";
|
|
|
|
export type RunMany = <Param>(injectionToken: InjectionToken<Runnable<Param>, void>) => Asyncify<Run<Param>>;
|
|
|
|
interface BarrierEvent {
|
|
finish: (id: string) => void;
|
|
}
|
|
|
|
class DynamicBarrier {
|
|
private readonly finishedIds = new Map<string, Promise<void>>();
|
|
private readonly events: TypedEventEmitter<BarrierEvent> = new EventEmitter();
|
|
|
|
private initFinishingPromise(id: string): Promise<void> {
|
|
return getOrInsert(this.finishedIds, id, new Promise<void>(resolve => {
|
|
const handler = (finishedId: string) => {
|
|
if (finishedId === id) {
|
|
resolve();
|
|
this.events.removeListener("finish", handler);
|
|
}
|
|
};
|
|
|
|
this.events.addListener("finish", handler);
|
|
}));
|
|
}
|
|
|
|
setFinished(id: string): void {
|
|
void this.initFinishingPromise(id);
|
|
|
|
this.events.emit("finish", id);
|
|
}
|
|
|
|
async blockOn(id: string): Promise<void> {
|
|
await this.initFinishingPromise(id);
|
|
}
|
|
}
|
|
|
|
const executeRunnableWith = <Param>(tokenId: string, param: Param) => {
|
|
const barrier = new DynamicBarrier();
|
|
|
|
return async (runnable: RunnableWithId<Param>): Promise<void> => {
|
|
for (const parentRunnable of runnable.runAfter) {
|
|
await barrier.blockOn(parentRunnable.id);
|
|
}
|
|
|
|
console.log(`^^^ "${tokenId}" @ "${runnable.id}"`)
|
|
await runnable.run(param);
|
|
console.log(`--- "${tokenId}" @ "${runnable.id}"`)
|
|
barrier.setFinished(runnable.id);
|
|
};
|
|
};
|
|
|
|
export function runManyFor(di: DiContainerForInjection): RunMany {
|
|
const convertToWithId = convertToWithIdWith(di);
|
|
|
|
return <Param>(injectionToken: InjectionToken<Runnable<Param>, void>) => async (param: Param) => {
|
|
const executeRunnable = executeRunnableWith(injectionToken.id, param);
|
|
const allRunnables = di.injectManyWithMeta(injectionToken).map(x => convertToWithId(x));
|
|
|
|
verifyRunnablesAreDAG(injectionToken.id, allRunnables);
|
|
|
|
await Promise.all(allRunnables.map(executeRunnable));
|
|
};
|
|
}
|