process-manager.js•3.96 kB
import { spawn } from 'child_process';
import { EventEmitter } from 'events';
export class ProcessManager extends EventEmitter {
constructor(config) {
super();
this.config = config;
this.process = null;
this.startTime = null;
}
async startTomcat(gradleCommand = 'appRun', workingDirectory = null) {
if (this.process) {
throw new Error('Tomcat is already running');
}
const workDir = workingDirectory || this.config.workingDirectory || process.cwd();
const command = gradleCommand || this.config.gradleCommand || 'appRun';
return new Promise((resolve, reject) => {
try {
this.process = spawn('./gradlew', [command], {
cwd: workDir,
stdio: ['pipe', 'pipe', 'pipe'],
detached: false
});
this.startTime = new Date();
this.process.stdout.on('data', (data) => {
this.emit('stdout', data.toString());
});
this.process.stderr.on('data', (data) => {
this.emit('stderr', data.toString());
});
this.process.on('error', (error) => {
this.emit('error', error);
this.cleanup();
reject(error);
});
this.process.on('exit', (code, signal) => {
this.emit('exit', { code, signal });
this.cleanup();
});
setTimeout(() => {
if (this.process && this.process.pid) {
resolve({
running: true,
pid: this.process.pid,
uptime: this.getUptime(),
port: this.config.port || null,
gradle_command: command
});
} else {
reject(new Error('Failed to start Tomcat process'));
}
}, 1000);
} catch (error) {
reject(error);
}
});
}
async stopTomcat(force = false) {
if (!this.process) {
return { success: true, message: 'Tomcat is not running' };
}
return new Promise((resolve) => {
const pid = this.process.pid;
if (force) {
this.process.kill('SIGKILL');
} else {
this.process.kill('SIGTERM');
}
const timeout = setTimeout(() => {
if (this.process) {
this.process.kill('SIGKILL');
}
resolve({ success: true, message: `Tomcat process ${pid} forcefully terminated` });
}, 10000);
this.process.on('exit', () => {
clearTimeout(timeout);
resolve({ success: true, message: `Tomcat process ${pid} terminated gracefully` });
});
});
}
async restartTomcat(force = false, gradleCommand = null) {
const stopResult = await this.stopTomcat(force);
await new Promise(resolve => setTimeout(resolve, 2000));
const startResult = await this.startTomcat(gradleCommand);
return {
stop: stopResult,
start: startResult,
success: true
};
}
getStatus() {
if (!this.process) {
return {
running: false,
pid: null,
uptime: null,
port: null,
gradle_command: null
};
}
return {
running: true,
pid: this.process.pid,
uptime: this.getUptime(),
port: this.config.port || null,
gradle_command: this.config.gradleCommand || 'appRun'
};
}
getUptime() {
if (!this.startTime) return null;
const now = new Date();
const diff = now - this.startTime;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
if (hours > 0) {
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
} else if (minutes > 0) {
return `${minutes}m ${seconds % 60}s`;
} else {
return `${seconds}s`;
}
}
cleanup() {
this.process = null;
this.startTime = null;
}
destroy() {
if (this.process) {
this.process.kill('SIGKILL');
this.cleanup();
}
}
}