openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
890 lines (829 loc) • 29.1 kB
JavaScript
var Agenda, Keystore, Q, User, activeApiConnections, activeHttpConnections, activeHttpsConnections, activePollingConnections, activeRerunConnections, activeTcpConnections, addWorker, agenda, alerts, apiHttpsServer, atna, auditTcpServer, auditTlsServer, auditUDPServer, auditing, autoRetry, chokidar, cluster, clusterArg, clusterSize, config, connectionATNA, connectionDefault, currentVersion, dgram, ensureKeystore, ensureRootUser, fs, himSourceID, http, httpServer, https, httpsServer, koaApi, koaMiddleware, logger, lookupServerPorts, mongoose, nconf, net, numCPUs, os, path, pem, polling, pollingServer, ports, ref, ref1, reports, rerunServer, rootUser, startAgenda, startApiServer, startAuditTcpTlsServer, startAuditUDPServer, startHttpServer, startHttpsServer, startPollingServer, startRerunServer, startTCPServersAndHttpReceiver, stop, stopAgenda, stopTasksProcessor, tasks, tcpAdapter, tcpHttpReceiver, tls, tlsAuthentication, trackConnection, upgradeDB, uuid;
require('source-map-support').install();
path = require('path');
global.appRoot = path.join(path.resolve(__dirname), '..');
config = require("./config/config");
config.mongo = config.get('mongo');
config.authentication = config.get('authentication');
config.router = config.get('router');
config.api = config.get('api');
config.rerun = config.get('rerun');
config.tcpAdapter = config.get('tcpAdapter');
config.logger = config.get('logger');
config.alerts = config.get('alerts');
config.polling = config.get('polling');
config.reports = config.get('reports');
config.auditing = config.get('auditing');
config.agenda = config.get('agenda');
config.certificateManagement = config.get('certificateManagement');
himSourceID = config.get('auditing').auditEvents.auditSourceID;
mongoose = require("mongoose");
exports.connectionDefault = connectionDefault = mongoose.createConnection(config.mongo.url);
exports.connectionATNA = connectionATNA = mongoose.createConnection(config.mongo.atnaUrl);
fs = require('fs');
http = require('http');
https = require('https');
tls = require('tls');
net = require('net');
dgram = require('dgram');
koaMiddleware = require("./koaMiddleware");
koaApi = require("./koaApi");
tlsAuthentication = require("./middleware/tlsAuthentication");
uuid = require('node-uuid');
Q = require('q');
logger = require('winston');
require('winston-mongodb').MongoDB;
logger.remove(logger.transports.Console);
cluster = require('cluster');
numCPUs = require('os').cpus().length;
nconf = require('nconf');
atna = require('atna-audit');
os = require('os');
currentVersion = require('../package.json').version;
chokidar = require('chokidar');
User = require('./model/users').User;
Keystore = require('./model/keystore').Keystore;
pem = require('pem');
Agenda = require('agenda');
alerts = require('./alerts');
reports = require('./reports');
polling = require('./polling');
tcpAdapter = require('./tcpAdapter');
auditing = require('./auditing');
tasks = require('./tasks');
upgradeDB = require('./upgradeDB');
autoRetry = require('./autoRetry');
clusterArg = nconf.get('cluster');
exports.setupCertificateWatcher = function() {
var certFile, keyFile, watcher;
certFile = config.certificateManagement.certPath;
keyFile = config.certificateManagement.keyPath;
return watcher = chokidar.watch([certFile, keyFile], {
usePolling: true
}).on('ready', function() {
logger.info('Certificate/Key watch paths:', watcher.getWatched());
return watcher.on('change', function(path, stats) {
var id, ref, worker;
ref = cluster.workers;
for (id in ref) {
worker = ref[id];
logger.debug("Restarting worker " + worker.id + "...");
worker.send({
type: 'restart'
});
}
});
});
};
if (cluster.isMaster && !module.parent) {
logger.add(logger.transports.Console, {
colorize: true,
timestamp: true,
label: "master",
level: config.logger.level
});
if (config.logger.logToDB === true) {
logger.add(logger.transports.MongoDB, {
db: config.mongo.url,
label: "master",
level: 'debug',
capped: config.logger.capDBLogs,
cappedSize: config.logger.capSize
});
}
if (clusterArg == null) {
clusterArg = 1;
}
if (clusterArg === 'auto') {
clusterSize = numCPUs;
} else {
clusterSize = clusterArg;
}
if (typeof clusterSize !== 'number' || clusterSize % 1 !== 0 || clusterSize < 1) {
throw new Error("invalid --cluster argument entered: " + clusterArg + ". Please enter a positive number or 'auto'.");
}
logger.info("Running OpenHIM Core JS version " + currentVersion);
logger.info("Clustering the OpenHIM with " + clusterSize + " workers...");
addWorker = function() {
var worker;
worker = cluster.fork();
return worker.on('message', function(msg) {
var id, ref, ref1, ref2, results, results1, results2;
logger.debug("Message received from worker " + worker.id, msg);
if (msg.type === 'restart-all') {
logger.debug("Restarting all workers...");
ref = cluster.workers;
results = [];
for (id in ref) {
worker = ref[id];
logger.debug("Restarting worker " + worker.id + "...");
results.push(worker.send({
type: 'restart'
}));
}
return results;
} else if (msg.type === 'start-tcp-channel') {
logger.info("Starting TCP channel for channel: " + msg.channelID);
ref1 = cluster.workers;
results1 = [];
for (id in ref1) {
worker = ref1[id];
logger.debug("Starting TCP channel on worker " + worker.id + "...");
results1.push(worker.send(msg));
}
return results1;
} else if (msg.type === 'stop-tcp-channel') {
logger.info("Stopping TCP channel for channel: " + msg.channelID);
ref2 = cluster.workers;
results2 = [];
for (id in ref2) {
worker = ref2[id];
logger.debug("Stopping TCP channel on worker " + worker.id + "...");
results2.push(worker.send(msg));
}
return results2;
} else if (msg.type === 'get-uptime') {
return worker.send({
type: 'get-uptime',
masterUptime: process.uptime()
});
}
});
};
upgradeDB.upgradeDb(function() {
var i, j, ref;
for (i = j = 1, ref = clusterSize; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {
addWorker();
}
cluster.on('exit', function(worker, code, signal) {
logger.warn("worker " + worker.process.pid + " died");
if (!worker.suicide) {
return addWorker();
}
});
cluster.on('online', function(worker) {
return logger.info("worker with pid " + worker.process.pid + " is online");
});
return cluster.on('listening', function(worker, address) {
return logger.debug("worker " + worker.id + " is now connected to " + address.address + ":" + address.port);
});
});
if (config.certificateManagement.watchFSForCert) {
exports.setupCertificateWatcher();
}
} else {
/* Setup Worker */
logger.add(logger.transports.Console, {
colorize: true,
timestamp: true,
label: ((ref = cluster.worker) != null ? ref.id : void 0) != null ? "worker" + cluster.worker.id : void 0,
level: config.logger.level
});
if (config.logger.logToDB === true) {
logger.add(logger.transports.MongoDB, {
db: config.mongo.url,
label: ((ref1 = cluster.worker) != null ? ref1.id : void 0) != null ? "worker" + cluster.worker.id : void 0,
level: 'debug',
capped: config.logger.capDBLogs,
cappedSize: config.logger.capSize
});
}
httpServer = null;
httpsServer = null;
apiHttpsServer = null;
rerunServer = null;
tcpHttpReceiver = null;
pollingServer = null;
auditUDPServer = null;
auditTlsServer = null;
auditTcpServer = null;
activeHttpConnections = {};
activeHttpsConnections = {};
activeApiConnections = {};
activeRerunConnections = {};
activeTcpConnections = {};
activePollingConnections = {};
trackConnection = function(map, socket) {
var id;
id = uuid.v4();
map[id] = socket;
socket.on('close', function() {
map[id] = null;
return delete map[id];
});
return socket.on('error', function(err) {
return logger.error(err);
});
};
exports.isTcpHttpReceiverRunning = function() {
return tcpHttpReceiver != null;
};
rootUser = {
firstname: 'Super',
surname: 'User',
email: 'root@openhim.org',
passwordAlgorithm: 'sha512',
passwordHash: '943a856bba65aad6c639d5c8d4a11fc8bb7fe9de62ae307aec8cf6ae6c1faab722127964c71db4bdd2ea2cdf60c6e4094dcad54d4522ab2839b65ae98100d0fb',
passwordSalt: 'd9bcb40e-ae65-478f-962e-5e5e5e7d0a01',
groups: ['admin']
};
agenda = null;
startAgenda = function() {
var defer;
defer = Q.defer();
agenda = new Agenda({
db: {
address: config.mongo.url
}
});
agenda.on("start", function(job) {
return logger.info("starting job: " + job.attrs.name + ", Last Ran at: " + job.attrs.lastRunAt);
});
agenda.on("fail", function(err, job) {
return logger.error("Job " + job.attrs.name + " failed with " + err.message);
});
agenda.on("complete", function(job) {
return logger.info("Job " + job.attrs.name + " has completed");
});
agenda.on("ready", function() {
if (config.alerts.enableAlerts) {
alerts.setupAgenda(agenda);
}
if (config.reports.enableReports) {
reports.setupAgenda(agenda);
}
autoRetry.setupAgenda(agenda);
if (config.polling.enabled) {
return polling.setupAgenda(agenda, function() {
return setTimeout(function() {
agenda.start();
defer.resolve();
return logger.info("Started agenda job scheduler");
}, config.agenda.startupDelay);
});
} else {
agenda.start();
return defer.resolve();
}
});
return defer.promise;
};
stopAgenda = function() {
var defer;
defer = Q.defer();
agenda.stop(function() {
defer.resolve();
return logger.info("Stopped agenda job scheduler");
});
return defer.promise;
};
startHttpServer = function(httpPort, bindAddress, app) {
var deferred;
deferred = Q.defer();
httpServer = http.createServer(app.callback());
httpServer.setTimeout(+config.router.timeout, function() {
return logger.info("HTTP socket timeout reached");
});
httpServer.listen(httpPort, bindAddress, function() {
logger.info("HTTP listening on port " + httpPort);
return deferred.resolve();
});
httpServer.on('error', function(err) {
return logger.error("An httpServer error occured: " + err);
});
httpServer.on('clientError', function(err) {
return logger.error("An httpServer clientError occured: " + err);
});
httpServer.on('connection', function(socket) {
return trackConnection(activeHttpConnections, socket);
});
return deferred.promise;
};
startHttpsServer = function(httpsPort, bindAddress, app) {
var deferred, mutualTLS;
deferred = Q.defer();
mutualTLS = config.authentication.enableMutualTLSAuthentication;
tlsAuthentication.getServerOptions(mutualTLS, function(err, options) {
if (err) {
return done(err);
}
httpsServer = https.createServer(options, app.callback());
httpsServer.setTimeout(+config.router.timeout, function() {
return logger.info("HTTPS socket timeout reached");
});
httpsServer.listen(httpsPort, bindAddress, function() {
logger.info("HTTPS listening on port " + httpsPort);
return deferred.resolve();
});
httpsServer.on('error', function(err) {
return logger.error("An httpsServer error occured: " + err);
});
httpsServer.on('clientError', function(err) {
return logger.error("An httpsServer clientError occured: " + err);
});
return httpsServer.on('secureConnection', function(socket) {
return trackConnection(activeHttpsConnections, socket);
});
});
return deferred.promise;
};
ensureRootUser = function(callback) {
return User.findOne({
email: 'root@openhim.org'
}, function(err, user) {
if (!user) {
user = new User(rootUser);
return user.save(function(err) {
if (err) {
logger.error("Could not save root user: " + err);
return callback(err);
}
logger.info("Root user created.");
return callback();
});
} else {
return callback();
}
});
};
ensureKeystore = function(callback) {
var getServerCertDetails;
getServerCertDetails = function(cert, callback) {
return pem.readCertificateInfo(cert, function(err, certInfo) {
if (err) {
logger.error(err.stack);
return callback(err);
}
return pem.getFingerprint(cert, function(err, fingerprint) {
if (err) {
logger.error(err.stack);
return callback(err);
}
certInfo.data = cert;
certInfo.fingerprint = fingerprint.fingerprint;
return callback(certInfo);
});
});
};
return Keystore.findOne({}, function(err, keystore) {
var cert, certPath, keyPath;
if (err) {
logger.error(err.stack);
return callback(err);
}
if (keystore == null) {
if (config.certificateManagement.watchFSForCert) {
certPath = config.certificateManagement.certPath;
keyPath = config.certificateManagement.keyPath;
} else {
certPath = appRoot + "/resources/certs/default/cert.pem";
keyPath = appRoot + "/resources/certs/default/key.pem";
}
cert = fs.readFileSync(certPath);
return getServerCertDetails(cert, function(certInfo) {
keystore = new Keystore({
cert: certInfo,
key: fs.readFileSync(keyPath),
ca: []
});
return keystore.save(function(err, keystore) {
if (err) {
logger.error("Could not save keystore: " + err.stack);
return callback(err);
}
logger.info("Default keystore created.");
return callback();
});
});
} else if (config.certificateManagement.watchFSForCert) {
cert = fs.readFileSync(config.certificateManagement.certPath);
return getServerCertDetails(cert, function(certInfo) {
keystore.cert = certInfo;
keystore.key = fs.readFileSync(config.certificateManagement.keyPath);
return keystore.save(function(err, keystore) {
if (err) {
logger.error("Could not save keystore: " + err.stack);
return callback(err);
}
logger.info("Updated keystore with cert and key from filesystem.");
return callback();
});
});
} else {
return callback();
}
});
};
startApiServer = function(apiPort, bindAddress, app) {
var deferred, mutualTLS;
deferred = Q.defer();
mutualTLS = false;
tlsAuthentication.getServerOptions(mutualTLS, function(err, options) {
if (err) {
logger.error("Could not fetch https server options: " + err);
}
apiHttpsServer = https.createServer(options, app.callback());
apiHttpsServer.listen(apiPort, bindAddress, function() {
logger.info("API HTTPS listening on port " + apiPort);
return ensureRootUser(function() {
return deferred.resolve();
});
});
return apiHttpsServer.on('secureConnection', function(socket) {
return trackConnection(activeApiConnections, socket);
});
});
return deferred.promise;
};
startTCPServersAndHttpReceiver = function(tcpHttpReceiverPort, app) {
var defer;
defer = Q.defer();
tcpHttpReceiver = http.createServer(app.callback());
tcpHttpReceiver.listen(tcpHttpReceiverPort, config.tcpAdapter.httpReceiver.host, function() {
logger.info("HTTP receiver for Socket adapter listening on port " + tcpHttpReceiverPort);
return tcpAdapter.startupServers(function(err) {
if (err) {
logger.error(err);
}
return defer.resolve();
});
});
tcpHttpReceiver.on('connection', function(socket) {
return trackConnection(activeTcpConnections, socket);
});
return defer.promise;
};
startRerunServer = function(httpPort, app) {
var deferredHttp;
deferredHttp = Q.defer();
rerunServer = http.createServer(app.callback());
rerunServer.listen(httpPort, config.rerun.host, function() {
logger.info("Transaction Rerun HTTP listening on port " + httpPort);
return deferredHttp.resolve();
});
rerunServer.on('connection', function(socket) {
return trackConnection(activeRerunConnections, socket);
});
return deferredHttp.promise;
};
startPollingServer = function(pollingPort, app) {
var defer;
defer = Q.defer();
pollingServer = http.createServer(app.callback());
pollingServer.listen(pollingPort, config.polling.host, function(err) {
if (err) {
logger.error(err);
}
logger.info('Polling port listening on port ' + pollingPort);
return defer.resolve();
});
pollingServer.on('connection', function(socket) {
return trackConnection(activePollingConnections, socket);
});
return defer.promise;
};
startAuditUDPServer = function(auditUDPPort, bindAddress) {
var defer;
defer = Q.defer();
auditUDPServer = dgram.createSocket('udp4');
auditUDPServer.on('listening', function() {
logger.info("Auditing UDP server listening on port " + auditUDPPort);
return defer.resolve();
});
auditUDPServer.on('message', function(msg, rinfo) {
logger.info("[Auditing UDP] Received message from " + rinfo.address + ":" + rinfo.port);
return auditing.processAudit(msg, function() {
return logger.info("[Auditing UDP] Processed audit");
});
});
auditUDPServer.on('error', function(err) {
if (err.code === 'EADDRINUSE') {
return defer.resolve();
} else {
logger.error("UDP Audit server error: " + err, err);
return defer.reject(err);
}
});
auditUDPServer.bind({
port: auditUDPPort,
address: bindAddress,
exclusive: true
});
return defer.promise;
};
startAuditTcpTlsServer = function(type, auditPort, bindAddress) {
var defer, handler;
defer = Q.defer();
handler = function(sock) {
var length, message;
message = "";
length = 0;
sock.on('data', function(data) {
var lengthIndex, lengthValue;
message += data.toString();
if (length === 0 && message.indexOf(' ') !== -1) {
lengthIndex = message.indexOf(" ");
lengthValue = message.substr(0, lengthIndex);
length = parseInt(lengthValue.trim());
message = message.substr(lengthIndex + 1);
}
if (isNaN(length)) {
logger.info("[Auditing " + type + "] No length supplied");
sock.destroy();
}
logger.debug("Length prefix is: " + length + " and message length so far is " + (Buffer.byteLength(message)));
if (length === Buffer.byteLength(message)) {
logger.info("[Auditing " + type + "] Received message from " + sock.remoteAddress);
auditing.processAudit(message, function() {
return logger.info("[Auditing " + type + "] Processed audit");
});
message = "";
return length = 0;
}
});
return sock.on('error', function(err) {
return logger.error(err);
});
};
if (type === 'TLS') {
tlsAuthentication.getServerOptions(true, function(err, options) {
if (err) {
return callback(err);
}
auditTlsServer = tls.createServer(options, handler);
return auditTlsServer.listen(auditPort, bindAddress, function() {
logger.info("Auditing TLS server listening on port " + auditPort);
return defer.resolve();
});
});
} else if (type === 'TCP') {
auditTcpServer = net.createServer(handler);
auditTcpServer.listen(auditPort, bindAddress, function() {
logger.info("Auditing TCP server listening on port " + auditPort);
return defer.resolve();
});
}
return defer.promise;
};
exports.start = function(ports, done) {
var bindAddress, promises;
bindAddress = config.get('bindAddress');
logger.info("Starting OpenHIM server on " + bindAddress + "...");
promises = [];
return ensureKeystore(function() {
var defer;
if (ports.httpPort || ports.httpsPort) {
koaMiddleware.setupApp(function(app) {
if (ports.httpPort) {
promises.push(startHttpServer(ports.httpPort, bindAddress, app));
}
if (ports.httpsPort) {
return promises.push(startHttpsServer(ports.httpsPort, bindAddress, app));
}
});
}
if (ports.apiPort && config.api.enabled) {
koaApi.setupApp(function(app) {
return promises.push(startApiServer(ports.apiPort, bindAddress, app));
});
}
if (ports.rerunHttpPort) {
koaMiddleware.rerunApp(function(app) {
return promises.push(startRerunServer(ports.rerunHttpPort, app));
});
if (config.rerun.processor.enabled) {
defer = Q.defer();
tasks.start(function() {
return defer.resolve();
});
promises.push(defer.promise);
}
}
if (ports.tcpHttpReceiverPort) {
koaMiddleware.tcpApp(function(app) {
return promises.push(startTCPServersAndHttpReceiver(ports.tcpHttpReceiverPort, app));
});
}
if (ports.pollingPort) {
koaMiddleware.pollingApp(function(app) {
return promises.push(startPollingServer(ports.pollingPort, app));
});
}
if (ports.auditUDPPort) {
promises.push(startAuditUDPServer(ports.auditUDPPort, bindAddress));
}
if (ports.auditTlsPort) {
promises.push(startAuditTcpTlsServer('TLS', ports.auditTlsPort, bindAddress));
}
if (ports.auditTcpPort) {
promises.push(startAuditTcpTlsServer('TCP', ports.auditTcpPort, bindAddress));
}
promises.push(startAgenda());
return (Q.all(promises)).then(function() {
var audit;
audit = atna.appActivityAudit(true, himSourceID, os.hostname(), 'system');
audit = atna.wrapInSyslog(audit);
return auditing.sendAuditEvent(audit, function() {
logger.info('Processed start audit event');
logger.info("OpenHIM server started: " + (new Date()));
return done();
});
});
});
};
stopTasksProcessor = function(callback) {
if (tasks.isRunning()) {
return tasks.stop(callback);
} else {
return callback();
}
};
exports.stop = stop = function(done) {
return stopTasksProcessor(function() {
var defer, err, error, key, promises, socket, stopServer;
promises = [];
stopServer = function(server, serverType) {
var deferred;
deferred = Q.defer();
server.close(function() {
logger.info("Stopped " + serverType + " server");
return deferred.resolve();
});
return deferred.promise;
};
if (httpServer) {
promises.push(stopServer(httpServer, 'HTTP'));
}
if (httpsServer) {
promises.push(stopServer(httpsServer, 'HTTPS'));
}
if (apiHttpsServer) {
promises.push(stopServer(apiHttpsServer, 'API HTTP'));
}
if (rerunServer) {
promises.push(stopServer(rerunServer, 'Rerun HTTP'));
}
if (pollingServer) {
promises.push(stopServer(pollingServer, 'Polling HTTP'));
}
if (agenda) {
promises.push(stopAgenda());
}
if (auditTlsServer) {
promises.push(stopServer(auditTlsServer, 'Audit TLS').promise);
}
if (auditTcpServer) {
promises.push(stopServer(auditTcpServer, 'Audit TCP').promise);
}
if (auditUDPServer) {
try {
auditUDPServer.close();
logger.info("Stopped Audit UDP server");
} catch (error) {
err = error;
}
}
if (tcpHttpReceiver) {
promises.push(stopServer(tcpHttpReceiver, 'TCP HTTP Receiver'));
defer = Q.defer();
tcpAdapter.stopServers(function() {
return defer.resolve();
});
promises.push(defer.promise);
}
for (key in activeHttpConnections) {
socket = activeHttpConnections[key];
socket.destroy();
}
for (key in activeHttpsConnections) {
socket = activeHttpsConnections[key];
socket.destroy();
}
for (key in activeApiConnections) {
socket = activeApiConnections[key];
socket.destroy();
}
for (key in activeRerunConnections) {
socket = activeRerunConnections[key];
socket.destroy();
}
for (key in activeTcpConnections) {
socket = activeTcpConnections[key];
socket.destroy();
}
for (key in activePollingConnections) {
socket = activePollingConnections[key];
socket.destroy();
}
return (Q.all(promises)).then(function() {
var audit;
httpServer = null;
httpsServer = null;
apiHttpsServer = null;
rerunServer = null;
tcpHttpReceiver = null;
pollingServer = null;
auditUDPServer = null;
auditTlsServer = null;
auditTcpServer = null;
agenda = null;
audit = atna.appActivityAudit(false, himSourceID, os.hostname(), 'system');
audit = atna.wrapInSyslog(audit);
return auditing.sendAuditEvent(audit, function() {
logger.info('Processed stop audit event');
logger.info('Server shutdown complete.');
return done();
});
});
});
};
lookupServerPorts = function() {
return {
httpPort: config.router.httpPort,
httpsPort: config.router.httpsPort,
apiPort: config.api.httpsPort,
rerunHttpPort: config.rerun.httpPort,
tcpHttpReceiverPort: config.tcpAdapter.httpReceiver.httpPort,
pollingPort: config.polling.pollingPort,
auditUDPPort: config.auditing.servers.udp.enabled ? config.auditing.servers.udp.port : void 0,
auditTlsPort: config.auditing.servers.tls.enabled ? config.auditing.servers.tls.port : void 0,
auditTcpPort: config.auditing.servers.tcp.enabled ? config.auditing.servers.tcp.port : void 0
};
};
if (!module.parent) {
ports = lookupServerPorts();
exports.start(ports, function() {
process.on('exit', stop);
process.on('SIGINT', function() {
return stop(process.exit);
});
process.on('SIGTERM', function() {
return stop(process.exit);
});
return process.on('message', function(msg) {
if (msg.type === 'restart') {
return exports.restartServer();
}
});
});
}
exports.restartServer = function(ports, done) {
if (typeof ports === 'function') {
done = ports;
ports = null;
}
if (typeof port === "undefined" || port === null) {
ports = lookupServerPorts();
}
return exports.stop(function() {
return exports.start(ports, function() {
if (done) {
return done();
}
});
});
};
exports.startRestartServerTimeout = function(done) {
if (cluster.isMaster) {
setTimeout(function() {
logger.debug('Master restarting itself...');
return exports.restartServer();
}, 2000);
} else {
setTimeout(function() {
logger.debug('Sending restart cluster message...');
return process.send({
type: 'restart-all'
});
}, 2000);
}
return done();
};
exports.getUptime = function(callback) {
var processEvent, uptime;
if (cluster.isMaster) {
uptime = {
master: process.uptime()
};
return callback(null, uptime);
} else {
process.send({
type: 'get-uptime'
});
processEvent = function(uptime) {
if (uptime.type === 'get-uptime') {
uptime = {
master: uptime.masterUptime
};
process.removeListener('message', processEvent);
return callback(null, uptime);
}
};
return process.on('message', processEvent);
}
};
}
if (process.env.NODE_ENV === 'test') {
exports.ensureKeystore = ensureKeystore;
}
//# sourceMappingURL=server.js.map