80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import { spawn, ChildProcessWithoutNullStreams } from 'child_process';
|
|
import path from 'path';
|
|
|
|
export default class PythonSubprocessManager {
|
|
// eslint-disable-next-line no-use-before-define
|
|
public static instance: PythonSubprocessManager | null = null;
|
|
|
|
private process: ChildProcessWithoutNullStreams | null = null;
|
|
|
|
private scriptPath: string;
|
|
|
|
private working_dir: string = path.join(
|
|
__dirname,
|
|
'..',
|
|
'..',
|
|
'..',
|
|
'audio-service',
|
|
);
|
|
|
|
public portNumber: number | null = null;
|
|
|
|
constructor(scriptPath: string) {
|
|
this.scriptPath = scriptPath;
|
|
PythonSubprocessManager.instance = this;
|
|
}
|
|
|
|
start(args: string[] = []): void {
|
|
if (this.process) {
|
|
throw new Error('Process already running.');
|
|
}
|
|
console.log(`Using Python working directory at: ${this.working_dir}`);
|
|
console.log(`Starting Python subprocess with script: ${this.scriptPath}`);
|
|
this.process = spawn(
|
|
'venv/Scripts/python.exe',
|
|
[this.scriptPath, ...args],
|
|
{
|
|
cwd: this.working_dir,
|
|
detached: false,
|
|
stdio: 'pipe',
|
|
},
|
|
);
|
|
this.process.stdout.on('data', (data: Buffer) => {
|
|
console.log(`Python stdout: ${data.toString()}`);
|
|
});
|
|
this.process.stderr.on('data', (data: Buffer) => {
|
|
// console.error(`Python stderr: ${data.toString()}`);
|
|
const lines = data.toString().split('\n');
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
for (const line of lines) {
|
|
const match = line.match(/Running on .*:(\d+)/);
|
|
if (match) {
|
|
const port = parseInt(match[1], 10);
|
|
console.log(`Detected port: ${port}`);
|
|
this.portNumber = port;
|
|
}
|
|
}
|
|
});
|
|
this.process.on('exit', () => {
|
|
console.log('Python subprocess exited.');
|
|
this.process = null;
|
|
});
|
|
}
|
|
|
|
stop(): void {
|
|
if (this.process) {
|
|
this.process.kill();
|
|
this.process = null;
|
|
}
|
|
}
|
|
|
|
restart(args: string[] = []): void {
|
|
this.stop();
|
|
this.start(args);
|
|
}
|
|
|
|
isHealthy(): boolean {
|
|
return !!this.process && !this.process.killed;
|
|
}
|
|
}
|