129 lines
5.0 KiB
TypeScript
129 lines
5.0 KiB
TypeScript
import { fork, ChildProcess } from 'child_process';
|
|
import path from 'path';
|
|
import { WindowManager } from "./window_manager";
|
|
|
|
export class WorkerManager {
|
|
private readonly pathToWorkerDir: string;
|
|
private windowManager: WindowManager;
|
|
private workers: ChildProcess[];
|
|
private cleanupInProgress: boolean = false;
|
|
|
|
constructor(pathToWorkerDir: string, windowManager: WindowManager) {
|
|
this.pathToWorkerDir = pathToWorkerDir;
|
|
this.windowManager = windowManager;
|
|
this.workers = [];
|
|
}
|
|
|
|
async startNetworkScannerWorker(udpPort: number, tcpPort: number, okPage: string, errorPage: string, databaseResetPage: string, userConfigPath: string, applicationInfoPath: string): Promise<void> {
|
|
return this.startForkedWorker('network_scanner_worker.js', {
|
|
UDP_PORT: udpPort.toString(),
|
|
TCP_PORT: tcpPort.toString(),
|
|
OK_PAGE: okPage,
|
|
ERROR_PAGE: errorPage,
|
|
DATABASE_RESET_PAGE: databaseResetPage,
|
|
USER_CONFIG_PATH: userConfigPath,
|
|
APPLICATION_INFO_PATH: applicationInfoPath
|
|
});
|
|
}
|
|
|
|
async startDirectoriesWatchersWorker(memoryManagerPath: string, applicationInfoPath: string): Promise<void> {
|
|
return this.startForkedWorker('directories_watcher_worker.js', {
|
|
MEMORY_MANAGER_PATH: memoryManagerPath,
|
|
APPLICATION_INFO_PATH: applicationInfoPath
|
|
});
|
|
}
|
|
|
|
async startServersWorker(host: string, udpPort: number, tcpPort: number): Promise<void> {
|
|
return this.startForkedWorker('servers_worker.js', {
|
|
HOST: host,
|
|
USER_UDP_PORT: udpPort.toString(),
|
|
USER_TCP_PORT: tcpPort.toString()
|
|
});
|
|
}
|
|
|
|
async startResourceCoordinatorWorker(usersConfigPath: string, applicationInfoPath: string, memoryManagerPath: string, queueManagerPath: string, tcpPort: number): Promise<void> {
|
|
return this.startForkedWorker('resource_coordinator_worker.js', {
|
|
USERS_CONFIG_PATH: usersConfigPath,
|
|
APPLICATION_INFO_PATH: applicationInfoPath,
|
|
MEMORY_MANAGER_PATH: memoryManagerPath,
|
|
QUEUE_MANAGER_PATH: queueManagerPath,
|
|
TCP_PORT: tcpPort.toString()
|
|
});
|
|
}
|
|
|
|
async startBackupRetrievalWorker(userConfigPath: string, applicationInfoPath: string, clientPort: number, destinationPath: string): Promise<void> {
|
|
return this.startForkedWorker('backup_retrieval_worker.js', {
|
|
USER_CONFIG_PATH: userConfigPath,
|
|
APPLICATION_INFO_PATH: applicationInfoPath,
|
|
CLIENT_PORT: clientPort.toString(),
|
|
DESTINATION_PATH: destinationPath
|
|
});
|
|
}
|
|
|
|
async startAnnouncementWorker(applicationInfoPath: string, clientPort: number, message: string): Promise<void> {
|
|
return this.startForkedWorker('send_announcement_worker.js', {
|
|
APPLICATION_INFO_PATH: applicationInfoPath,
|
|
CLIENT_PORT: clientPort.toString(),
|
|
MESSAGE: message
|
|
});
|
|
}
|
|
|
|
private async startForkedWorker(scriptName: string, envData: { [key: string]: string }): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const worker = fork(path.join(this.pathToWorkerDir, scriptName), {
|
|
execArgv: ['--max-old-space-size=4096'],
|
|
env: { ...process.env, ...envData }
|
|
});
|
|
|
|
this.workers.push(worker);
|
|
|
|
worker.on('message', (data: unknown) => {
|
|
const message = data as { type: string, page?: string, message?: string };
|
|
|
|
if (message.type === 'changeContent' && message.page) {
|
|
this.windowManager.changeContent(message.page);
|
|
} else if (message.type === 'showAlert' && message.message) {
|
|
this.windowManager.showAlert(message.message);
|
|
} else {
|
|
console.log(`${scriptName} message:`, message);
|
|
}
|
|
});
|
|
|
|
worker.on('error', (err) => {
|
|
console.error(`${scriptName} error:`, err);
|
|
worker.kill();
|
|
this.removeWorker(worker);
|
|
reject(err);
|
|
});
|
|
|
|
worker.on('exit', (code, signal) => {
|
|
this.removeWorker(worker);
|
|
if (code === 0) {
|
|
console.log(`${scriptName} exited successfully`);
|
|
resolve();
|
|
} else if (signal) {
|
|
console.log(`${scriptName} was killed with signal: ${signal}`);
|
|
} else {
|
|
console.error(`${scriptName} exited with code: ${code}`);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
closeAllWorkers(): void {
|
|
if (this.cleanupInProgress) return;
|
|
this.cleanupInProgress = true;
|
|
|
|
console.log('Terminating all running workers...');
|
|
this.workers.forEach(worker => worker.kill());
|
|
this.workers = [];
|
|
}
|
|
|
|
private removeWorker(worker: ChildProcess): void {
|
|
const index = this.workers.indexOf(worker);
|
|
if (index > -1) {
|
|
this.workers.splice(index, 1);
|
|
}
|
|
}
|
|
}
|