141 lines
3.7 KiB
TypeScript
141 lines
3.7 KiB
TypeScript
import {
|
|
FilesChangeNotifierService,
|
|
IHashesCache,
|
|
} from "./files_change_notifier_service";
|
|
import { IPipeline } from "../model/process_model";
|
|
import { ExecutorProgramService } from "./executor_program_service";
|
|
import { EXEC_EVENT, ExecError, SpawnError } from "../model/exec_error_model";
|
|
import { TypedEvent } from "../helper/typed_event";
|
|
import { Result } from "../helper/result";
|
|
import { ExecutorResult } from "../model/executor_result";
|
|
import { delay } from "../helper/delay";
|
|
import { TriggerService } from "./trigger_service";
|
|
import { Trigger } from "../../features/triggers/trigger_model";
|
|
|
|
export interface Iteration {
|
|
hashes: IHashesCache | null;
|
|
process: IPipeline;
|
|
result?: ExecError | SpawnError | ExecutorResult;
|
|
}
|
|
|
|
export abstract class IStackService {
|
|
abstract callStack: Iteration[];
|
|
abstract path: string;
|
|
abstract init(processed: IPipeline[], path: string): void;
|
|
}
|
|
|
|
export class StackService
|
|
extends TypedEvent<Iteration[]>
|
|
implements IStackService
|
|
{
|
|
callStack: Iteration[];
|
|
path: string;
|
|
constructor(processed: IPipeline[], path: string) {
|
|
super();
|
|
this.path = path;
|
|
this.callStack = [];
|
|
this.init(processed);
|
|
}
|
|
|
|
public init(processed: IPipeline[]) {
|
|
for (let el of processed) {
|
|
el = this.commandHandler(el);
|
|
this.callStack.push({
|
|
hashes: null,
|
|
process: el,
|
|
});
|
|
}
|
|
}
|
|
private commandHandler(processMetaData: IPipeline) {
|
|
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;
|
|
this.emit(this.callStack);
|
|
}
|
|
}
|
|
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 | null,
|
|
stackNumber: number
|
|
): Promise<Result<boolean, boolean>> {
|
|
if (trigger !== null) {
|
|
const hashes = this.callStack[stackNumber].hashes;
|
|
|
|
if (hashes != null) {
|
|
return await new TriggerService(trigger, hashes, this.path).call();
|
|
}
|
|
throw new Error("Hashes is null");
|
|
}
|
|
return Result.ok();
|
|
}
|
|
}
|