change files structure

This commit is contained in:
IDONTSUDO 2023-08-31 17:06:55 +03:00
parent 3210e72b22
commit 1ed6449ac6
30 changed files with 7 additions and 7 deletions

View file

@ -0,0 +1,82 @@
import cluster, { Worker } from "node:cluster";
import { TypedEvent } from "../helper/typed_event.js";
import { Result } from "../helper/result.js";
import { WorkerDataExec, WorkerType } from "../helper/worker_computed.js";
import { delay } from "../helper/delay.js";
import { ExecutorResult } from "../model/executor_result.js";
import { EXEC_TYPE, ExecError, SpawnError } from "../model/exec_error_model.js";
abstract class IExecutorProgramService {
abstract execPath: string;
}
export class ExecutorProgramService
extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
implements IExecutorProgramService
{
static event = "ExecutorProgramService";
execPath: string;
worker: Worker | any;
maxTime: null | number = null;
constructor(execPath: string, maxTime: number | null = null) {
super();
this.execPath = execPath;
this.maxTime = maxTime;
}
private async workerExecuted(command: string, workerType: WorkerType,args:Array<string> | undefined = undefined) {
cluster.setupPrimary({
exec: "./src/core/helper/worker_computed.js",
});
const worker = cluster.fork();
await delay(300);
this.worker = worker;
const workerDataExec: WorkerDataExec = {
command: command,
execPath: this.execPath,
type: workerType,
cliArgs:args
};
worker.send(workerDataExec);
worker.on("message", (e) => {
const spawnError = SpawnError.isError(e);
if (spawnError instanceof SpawnError) {
this.emit(Result.error(spawnError));
}
const executorResult = ExecutorResult.isExecutorResult(e);
if (executorResult instanceof ExecutorResult) {
this.emit(Result.ok(executorResult));
}
const execError = ExecError.isExecError(e);
if (execError instanceof ExecError) {
this.emit(Result.error(execError));
}
});
if (this.maxTime != null) {
setTimeout(() => {
this.worker.kill();
this.emit(
Result.error(
WorkerType.EXEC
? new ExecError(command, "timeout err")
: new SpawnError(command, "timeout err")
)
);
}, this.maxTime!);
}
}
public async call(type: EXEC_TYPE, command: string, args:Array<string> | undefined = undefined): Promise<void> {
if (type == EXEC_TYPE.EXEC) {
this.workerExecuted(command, WorkerType.EXEC);
return;
}
this.workerExecuted(command, WorkerType.SPAWN,args);
return;
}
}

View file

@ -0,0 +1,122 @@
import * as fs from "fs";
import { resolve } from "node:path";
import { promisify } from "node:util";
import { createHash } from "node:crypto";
import "reflect-metadata";
import { BinaryLike } from "crypto";
import { EventsFileChanger, MetaDataFileManagerModel } from "../model/meta_data_file_manager_model.js";
import { Result } from "../helper/result.js";
import { TypedEvent } from "../helper/typed_event.js";
const readFileAsync = promisify(fs.readFile);
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
function md5(content: Buffer | BinaryLike) {
return createHash("md5").update(content).digest("hex");
}
interface IHashesCache {
[key: string]: MetaDataFileManagerModel;
}
export abstract class IFilesChangeNotifierService {
abstract directory: string;
}
export class FilesChangeNotifierService
extends TypedEvent<Result<Error, IHashesCache>>
implements IFilesChangeNotifierService
{
watcher!: fs.FSWatcher;
directory: string;
constructor(directory: string) {
super();
this.directory = directory;
this.init();
}
hashes: IHashesCache = {};
async init() {
const files = await this.getFiles(this.directory);
for (const file of files) {
await this.setHash(file);
}
}
async setHash(file: string) {
const data = await readFileAsync(file);
const md5Current = md5(data);
this.hashes[file] = new MetaDataFileManagerModel(
file,
md5Current,
EventsFileChanger.static
);
this.emit(Result.ok(this.hashes));
}
async getFiles(dir: string): Promise<string | any[]> {
const subdirs = await readdir(dir);
const files = await Promise.all(
subdirs.map(async (subdir) => {
const res = resolve(dir, subdir);
return (await stat(res)).isDirectory() ? this.getFiles(res) : res;
})
);
return files.reduce((a: string | any[], f: any) => a.concat(f), []);
}
public call = (): Result<Error, boolean> => {
try {
let md5Previous: string | null = null;
let fsWait: NodeJS.Timeout | boolean = false;
const watcher = fs.watch(
this.directory,
{ recursive: true },
async (_e, filename) => {
const filePath = this.directory + filename;
if (filename) {
if (fsWait) return;
fsWait = setTimeout(() => {
fsWait = false;
}, 100);
try {
const file = await readFileAsync(filePath);
const md5Current = md5(file);
if (md5Current === md5Previous) {
return;
}
const status = this.hashes[filePath] === undefined
? EventsFileChanger.create
: EventsFileChanger.update;
const model = new MetaDataFileManagerModel(
filePath,
md5Current,
status
);
this.hashes[filePath] = model;
md5Previous = md5Current;
this.emit(Result.ok(this.hashes));
} catch (error) {
this.emit(Result.ok(this.hashes));
this.hashes[filePath] = new MetaDataFileManagerModel(
filePath,
null,
EventsFileChanger.delete
);
}
}
}
);
this.watcher = watcher;
return Result.ok(true);
} catch (error) {
return Result.error(error as Error);
}
};
cancel() {
if (this.watcher != undefined) {
this.watcher.close();
this.listenersOncer = []
}
}
}