137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
import {
|
|
FilesChangeNotifierService,
|
|
IHashesCache,
|
|
} from "./files_change_notifier_service.js";
|
|
import { ProcessMetaData, Trigger } from "../model/process_model.js";
|
|
import { ExecutorProgramService } from "./executor_program_service.js";
|
|
import {
|
|
EXEC_EVENT,
|
|
ExecError,
|
|
SpawnError,
|
|
} from "../model/exec_error_model.js";
|
|
import { TypedEvent } from "../helper/typed_event.js";
|
|
import { Result } from "../helper/result.js";
|
|
import { ExecutorResult } from "../model/executor_result.js";
|
|
import { delay } from "../helper/delay.js";
|
|
import { TriggerErrorReport, TriggerService } from "./trigger_service.js";
|
|
|
|
export interface Iteration {
|
|
hashes: IHashesCache | null;
|
|
process: ProcessMetaData;
|
|
result?: ExecError | SpawnError | ExecutorResult;
|
|
}
|
|
|
|
export abstract class IStackService {
|
|
abstract callStack: Iteration[];
|
|
abstract path: string;
|
|
abstract init(processed: ProcessMetaData[], path: string): void;
|
|
}
|
|
|
|
export class StackService extends TypedEvent<string> implements IStackService {
|
|
callStack: Iteration[];
|
|
path: string;
|
|
constructor(processed: ProcessMetaData[], path: string) {
|
|
super();
|
|
this.path = path;
|
|
this.callStack = [];
|
|
this.init(processed);
|
|
}
|
|
|
|
public init(processed: ProcessMetaData[]) {
|
|
for (let el of processed) {
|
|
el = this.commandHandler(el);
|
|
this.callStack.push({
|
|
hashes: null,
|
|
process: el,
|
|
});
|
|
}
|
|
}
|
|
private commandHandler(processMetaData: ProcessMetaData) {
|
|
processMetaData.process.command = processMetaData.process.command.replace(
|
|
"$PATH",
|
|
this.path
|
|
);
|
|
return processMetaData;
|
|
}
|
|
public async call() {
|
|
let inc = 0;
|
|
|
|
for await (const el of this.callStack!) {
|
|
await this.execStack(inc, el);
|
|
inc += 1;
|
|
}
|
|
}
|
|
async execStack(
|
|
stackNumber: number,
|
|
stackLayer: Iteration
|
|
): Promise<void | boolean> {
|
|
const executorService = new ExecutorProgramService(this.path);
|
|
|
|
executorService.call(
|
|
stackLayer.process.process.type,
|
|
stackLayer.process.process.command
|
|
);
|
|
|
|
const filesChangeNotifierService = new FilesChangeNotifierService(
|
|
this.path
|
|
);
|
|
|
|
filesChangeNotifierService.call();
|
|
const result = await this.waitEvent<
|
|
Result<ExecError | SpawnError, ExecutorResult>
|
|
>(executorService);
|
|
await delay(100);
|
|
if (result.isSuccess()) {
|
|
this.callStack[stackNumber].result = result.value;
|
|
this.callStack[stackNumber].hashes = filesChangeNotifierService.hashes;
|
|
|
|
const triggerResult = await this.triggerExec(
|
|
stackLayer.process.trigger,
|
|
stackNumber
|
|
);
|
|
triggerResult.fold(
|
|
(s) => {
|
|
s
|
|
},
|
|
(e) => {
|
|
e;
|
|
}
|
|
);
|
|
}
|
|
|
|
filesChangeNotifierService.cancel();
|
|
return;
|
|
}
|
|
public waitEvent<T>(stream: TypedEvent<T>): Promise<T> {
|
|
const promise = new Promise<T>((resolve, reject) => {
|
|
const addListener = () => {
|
|
stream.on((e) => {
|
|
const event = e as Result<ExecError | SpawnError, ExecutorResult>;
|
|
event.fold(
|
|
(s) => {
|
|
if (s.event === EXEC_EVENT.END) {
|
|
resolve(e);
|
|
}
|
|
},
|
|
(e) => {
|
|
reject(e);
|
|
}
|
|
);
|
|
});
|
|
};
|
|
addListener();
|
|
});
|
|
return promise;
|
|
}
|
|
private async triggerExec(
|
|
trigger: Trigger,
|
|
stackNumber: number
|
|
): Promise<Result<boolean, boolean>> {
|
|
const hashes = this.callStack[stackNumber].hashes;
|
|
|
|
if (hashes != null) {
|
|
return await new TriggerService(trigger, hashes, this.path).call();
|
|
}
|
|
throw new Error("Hashes is null");
|
|
}
|
|
}
|