Add bun.lock for dependency management, update package version to 2025.1.0, refine TypeScript dependencies, and introduce tsconfig.build.json for type declaration output. Enhance RtmpPush class with dependency injection for command building and process management, and implement new interfaces for better extensibility.
This commit is contained in:
85
src/implementations/ProcessManager.ts
Normal file
85
src/implementations/ProcessManager.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import {ChildProcess} from 'node:child_process';
|
||||
import type {IProcessManager, ProcessManagerEvents} from '../interfaces/IProcessManager.js';
|
||||
import type {IProcessSpawner} from '../interfaces/IProcessSpawner.js';
|
||||
import type {ILogger} from '../interfaces/ILogger.js';
|
||||
import {EventEmitter} from 'node:events';
|
||||
|
||||
/**
|
||||
* Manages process lifecycle
|
||||
* Single Responsibility: Process management only
|
||||
* Open/Closed: Can be extended without modification
|
||||
*/
|
||||
export class ProcessManager extends EventEmitter implements IProcessManager {
|
||||
private activeProcess: ChildProcess | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly processSpawner: IProcessSpawner,
|
||||
private readonly logger: ILogger
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
start(command: string, args: string[]): void {
|
||||
if (this.isRunning()) {
|
||||
throw new Error('Process is already running');
|
||||
}
|
||||
|
||||
if (!command) {
|
||||
throw new Error('Invalid command: command cannot be empty');
|
||||
}
|
||||
|
||||
try {
|
||||
this.activeProcess = this.processSpawner.spawn(command, args);
|
||||
|
||||
if (!this.activeProcess) {
|
||||
throw new Error('Failed to spawn process');
|
||||
}
|
||||
|
||||
this.setupEventHandlers();
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to start process:', error);
|
||||
this.activeProcess = null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.activeProcess) {
|
||||
this.activeProcess.kill();
|
||||
this.activeProcess = null;
|
||||
}
|
||||
}
|
||||
|
||||
isRunning(): boolean {
|
||||
return this.activeProcess !== null && !this.activeProcess.killed;
|
||||
}
|
||||
|
||||
private setupEventHandlers(): void {
|
||||
if (!this.activeProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeProcess.stdout?.on('data', (data: Buffer) => {
|
||||
this.logger.log(`stdout: ${data}`);
|
||||
this.emit('data', data);
|
||||
});
|
||||
|
||||
this.activeProcess.stderr?.on('data', (data: Buffer) => {
|
||||
this.logger.log(`stderr: ${data}`);
|
||||
this.emit('data', data);
|
||||
});
|
||||
|
||||
this.activeProcess.on('close', (code: number | null) => {
|
||||
this.logger.log(`child process exited with code ${code}`);
|
||||
this.activeProcess = null;
|
||||
this.emit('close', code);
|
||||
});
|
||||
|
||||
this.activeProcess.on('error', (error: Error) => {
|
||||
this.logger.error('Process error:', error);
|
||||
this.activeProcess = null;
|
||||
this.emit('error', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user