mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 03:35:47 +02:00
216 lines
6.7 KiB
JavaScript
Executable file
216 lines
6.7 KiB
JavaScript
Executable file
'use strict'
|
|
|
|
var extend = require('extend');
|
|
var util = require('util');
|
|
var events = require('events');
|
|
var childProcess = require('child_process');
|
|
var fs = require('fs');
|
|
|
|
const ProcessGroupStates = {
|
|
STOPPED: 'stopped',
|
|
STARTED: 'started',
|
|
STOPPING: 'stopping'
|
|
};
|
|
|
|
const ProcessStates = {
|
|
STOPPED: 'stopped',
|
|
STARTED: 'started',
|
|
STOPPING: 'stopping'
|
|
};
|
|
|
|
function ProcessGroup(name, processes) {
|
|
events.EventEmitter.call(this);
|
|
|
|
this.name = name;
|
|
this.state = ProcessGroupStates.STOPPED;
|
|
this.processes = [];
|
|
this.restarting = false;
|
|
|
|
for (let process of processes) {
|
|
this.addProcess(process);
|
|
}
|
|
};
|
|
util.inherits(ProcessGroup, events.EventEmitter);
|
|
ProcessGroup.prototype = extend(ProcessGroup.prototype, {
|
|
addProcess: function(process) {
|
|
this.processes.push(process);
|
|
process.on('state-update', this.onProcessStateUpdate.bind(this));
|
|
},
|
|
start: function() {
|
|
if (this.state != ProcessGroupStates.STOPPED) {
|
|
console.warn("Can't start process group that is not stopped.");
|
|
return;
|
|
}
|
|
|
|
for (let process of this.processes) {
|
|
process.start();
|
|
}
|
|
|
|
this.state = ProcessGroupStates.STARTED;
|
|
},
|
|
stop: function() {
|
|
if (this.state != ProcessGroupStates.STARTED) {
|
|
console.warn("Can't stop process group that is not started.");
|
|
return;
|
|
}
|
|
for (let process of this.processes) {
|
|
process.stop();
|
|
}
|
|
this.state = ProcessGroupStates.STOPPING;
|
|
},
|
|
restart: function() {
|
|
if (this.state == ProcessGroupStates.STOPPED) {
|
|
// start the group, we were already stopped
|
|
this.start();
|
|
} else {
|
|
// set our restart flag so the group will restart once stopped
|
|
this.restarting = true;
|
|
|
|
// call stop, that will put them in the stopping state
|
|
this.stop();
|
|
}
|
|
},
|
|
|
|
// Event handlers
|
|
onProcessStateUpdate: function(process) {
|
|
var processesStillRunning = false;
|
|
for (let process of this.processes) {
|
|
if (process.state != ProcessStates.STOPPED) {
|
|
processesStillRunning = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!processesStillRunning) {
|
|
this.state = ProcessGroupStates.STOPPED;
|
|
|
|
// if we we're supposed to restart, call start now and reset the flag
|
|
if (this.restarting) {
|
|
this.start();
|
|
this.restarting = false;
|
|
}
|
|
}
|
|
this.emit('state-update', this, process);
|
|
}
|
|
});
|
|
|
|
var ID = 0;
|
|
function Process(name, command, commandArgs, logDirectory) {
|
|
events.EventEmitter.call(this);
|
|
|
|
this.id = ++ID;
|
|
this.name = name;
|
|
this.command = command;
|
|
this.commandArgs = commandArgs ? commandArgs : [];
|
|
this.child = null;
|
|
this.logDirectory = logDirectory;
|
|
|
|
this.state = ProcessStates.STOPPED;
|
|
};
|
|
util.inherits(Process, events.EventEmitter);
|
|
Process.prototype = extend(Process.prototype, {
|
|
start: function() {
|
|
if (this.state != ProcessStates.STOPPED) {
|
|
console.warn("Can't start process that is not stopped.");
|
|
return;
|
|
}
|
|
console.log("Starting " + this.command);
|
|
|
|
var logStdout = 'ignore',
|
|
logStderr = 'ignore';
|
|
|
|
if (this.logDirectory) {
|
|
var logDirectoryCreated = false;
|
|
|
|
try {
|
|
fs.mkdirSync('logs');
|
|
logDirectoryCreated = true;
|
|
} catch (e) {
|
|
if (e.code == 'EEXIST') {
|
|
logDirectoryCreated = true;
|
|
} else {
|
|
console.error("Error creating log directory");
|
|
}
|
|
}
|
|
|
|
if (logDirectoryCreated) {
|
|
// Create a temporary file with the current time
|
|
var time = (new Date).getTime();
|
|
var tmpLogStdout = this.logDirectory + '/' + this.name + '-' + time + '-stdout.txt';
|
|
var tmpLogStderr = this.logDirectory + '/' + this.name + '-' + time + '-stderr.txt';
|
|
|
|
try {
|
|
logStdout = fs.openSync(tmpLogStdout, 'ax');
|
|
} catch(e) {
|
|
console.log("Error creating stdout log file", e);
|
|
logStdout = 'ignore';
|
|
}
|
|
try {
|
|
logStderr = fs.openSync(tmpLogStderr, 'ax');
|
|
} catch(e) {
|
|
console.log("Error creating stderr log file", e);
|
|
logStderr = 'ignore';
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
this.child = childProcess.spawn(this.command, this.commandArgs, {
|
|
detached: false,
|
|
stdio: ['ignore', logStdout, logStderr]
|
|
});
|
|
} catch (e) {
|
|
console.log("Got error starting child process for " + this.name, e);
|
|
this.child = null;
|
|
this.state = ProcessStates.STOPPED;
|
|
}
|
|
|
|
if (logStdout != 'ignore') {
|
|
var pidLogStdout = './logs/' + this.name + "-" + this.child.pid + "-" + time + "-stdout.txt";
|
|
fs.rename(tmpLogStdout, pidLogStdout, function(e) {
|
|
if (e !== null) {
|
|
console.log("Error renaming log file from " + tmpLogStdout + " to " + pidLogStdout, e);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (logStderr != 'ignore') {
|
|
var pidLogStderr = './logs/' + this.name + "-" + this.child.pid + "-" + time + "-stderr.txt";
|
|
fs.rename(tmpLogStderr, pidLogStderr, function(e) {
|
|
if (e !== null) {
|
|
console.log("Error renaming log file from " + tmpLogStdout + " to " + pidLogStdout, e);
|
|
}
|
|
});
|
|
}
|
|
|
|
this.child.on('error', this.onChildStartError.bind(this));
|
|
this.child.on('close', this.onChildClose.bind(this));
|
|
this.state = ProcessStates.STARTED;
|
|
console.log("Child process started");
|
|
|
|
this.emit('state-update', this);
|
|
},
|
|
stop: function() {
|
|
if (this.state != ProcessStates.STARTED) {
|
|
console.warn("Can't stop process that is not started.");
|
|
return;
|
|
}
|
|
this.child.kill();
|
|
this.state = ProcessStates.STOPPING;
|
|
},
|
|
|
|
// Events
|
|
onChildStartError: function(error) {
|
|
console.log("Child process error ", error);
|
|
this.state = ProcessStates.STOPPED;
|
|
this.emit('state-update', this);
|
|
},
|
|
onChildClose: function(code) {
|
|
console.log("Child process closed with code ", code);
|
|
this.state = ProcessStates.STOPPED;
|
|
this.emit('state-update', this);
|
|
}
|
|
});
|
|
|
|
module.exports.Process = Process;
|
|
module.exports.ProcessGroup = ProcessGroup;
|
|
module.exports.ProcessStates = ProcessStates;
|