feat(core): Introduce ProcessMonitor with memory management and spawning features
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { spawn, ChildProcess } from 'child_process';
|
||||
import psTree from 'ps-tree';
|
||||
import pidusage from 'pidusage';
|
||||
import * as plugins from './plugins.js';
|
||||
|
||||
interface IMonitorConfig {
|
||||
export interface IMonitorConfig {
|
||||
name?: string; // Optional name to identify the instance
|
||||
projectDir: string; // Directory where the command will run
|
||||
command: string; // Full command to run (e.g., "npm run xyz")
|
||||
@@ -11,8 +9,8 @@ interface IMonitorConfig {
|
||||
monitorIntervalMs?: number; // Interval (in ms) at which memory is checked (default: 5000)
|
||||
}
|
||||
|
||||
class ProcessMonitor {
|
||||
private child: ChildProcess | null = null;
|
||||
export class ProcessMonitor {
|
||||
private child: plugins.childProcess.ChildProcess | null = null;
|
||||
private config: IMonitorConfig;
|
||||
private intervalId: NodeJS.Timeout | null = null;
|
||||
private stopped: boolean = true; // Initially stopped until start() is called
|
||||
@@ -46,7 +44,7 @@ class ProcessMonitor {
|
||||
', '
|
||||
)}] in directory: ${this.config.projectDir}`
|
||||
);
|
||||
this.child = spawn(this.config.command, this.config.args, {
|
||||
this.child = plugins.childProcess.spawn(this.config.command, this.config.args, {
|
||||
cwd: this.config.projectDir,
|
||||
detached: true,
|
||||
stdio: 'inherit',
|
||||
@@ -56,7 +54,7 @@ class ProcessMonitor {
|
||||
`Spawning command "${this.config.command}" in directory: ${this.config.projectDir}`
|
||||
);
|
||||
// Use shell mode to allow a full command string.
|
||||
this.child = spawn(this.config.command, {
|
||||
this.child = plugins.childProcess.spawn(this.config.command, {
|
||||
cwd: this.config.projectDir,
|
||||
detached: true,
|
||||
stdio: 'inherit',
|
||||
@@ -107,11 +105,11 @@ class ProcessMonitor {
|
||||
*/
|
||||
private getProcessGroupMemory(pid: number): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
psTree(pid, (err, children) => {
|
||||
plugins.psTree(pid, (err, children) => {
|
||||
if (err) return reject(err);
|
||||
// Include the main process and its children.
|
||||
const pids: number[] = [pid, ...children.map(child => Number(child.PID))];
|
||||
pidusage(pids, (err, stats) => {
|
||||
plugins.pidusage(pids, (err, stats) => {
|
||||
if (err) return reject(err);
|
||||
let totalMemory = 0;
|
||||
for (const key in stats) {
|
||||
@@ -157,22 +155,3 @@ class ProcessMonitor {
|
||||
console.log(prefix + message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
const config: IMonitorConfig = {
|
||||
name: 'Project XYZ Monitor', // Identifier for the instance
|
||||
projectDir: '/path/to/your/project', // Set the project directory here
|
||||
command: 'npm run xyz', // Full command string (no need for args)
|
||||
memoryLimitBytes: 500 * 1024 * 1024, // 500 MB memory limit
|
||||
monitorIntervalMs: 5000, // Check memory usage every 5 seconds
|
||||
};
|
||||
|
||||
const monitor = new ProcessMonitor(config);
|
||||
monitor.start();
|
||||
|
||||
// Ensure that on process exit (e.g. Ctrl+C) we clean up the child process and prevent respawns.
|
||||
process.on('SIGINT', () => {
|
||||
monitor.log('Received SIGINT, stopping monitor...');
|
||||
monitor.stop();
|
||||
process.exit();
|
||||
});
|
Reference in New Issue
Block a user