cluster-service
Version:
Turns your single process code into a fault-resilient multi-process service with built-in REST & CLI support
115 lines (100 loc) • 2.75 kB
JavaScript
var cservice = require("../cluster-service"),
cluster = require("cluster");
exports.get = get;
exports.monitor = monitor;
exports.getByPID = getByPID;
exports.getByPIDFromCache = getByPIDFromCache;
exports.exitGracefully = exitGracefully;
exports.demote = demote;
function get() {
var workers = [];
var cworkers = cluster.workers;
var k;
var worker;
for (k in cworkers) {
worker = cworkers[k];
if ((!worker.isDead || !worker.isDead())
&& worker.exitedAfterDisconnect !== true
&& worker.state !== "none") {
worker.pid = worker.process.pid;
workers.push(worker);
}
}
workers.send = send;
return workers;
}
// i hate O(N) lookups, but not hit hard enough to worry about optimizing at
// this point. freshness is more important
function getByPID(pid) {
var workers = get();
var i;
var worker;
for (i = 0; i < workers.length; i++) {
worker = workers[i];
if (worker.pid === pid) {
return worker;
}
}
// else return undefined
}
function getByPIDFromCache(pid) {
return cservice.locals.workers[pid];
}
function monitor() {
process.on("message", function(msg) {
if (!cservice.msgBus.isValidMessage(msg)) {
return; // end
}
switch (msg.cservice.cmd) {
case "processDetails":
cservice.processSafeSend(process,
cservice.msgBus.createMessage("processDetails", {
processDetails: {
memory: process.memoryUsage(),
title: process.title,
uptime: process.uptime(),
hrtime: process.hrtime()
}
}));
break;
}
});
}
function demote() {
// only demote if:
// 1. process.getgid is defined (not Windows)
// 2. Running as root
// 3. workerGid is string and not a proxy worker
var gid = cservice.options.workerGid || 'nobody';
var uid = cservice.options.workerUid || 'nobody';
if (process.getgid && process.getgid() === 0) {
if ( // but do not auto-demote proxy
// workers as they require priveledged port access
cluster.worker.env.type !== "proxy" &&
typeof cservice.options.workerGid === 'string'
) {
process.setgid(gid);
process.setuid(uid);
} else {
cservice.log(
"Worker running as root. Not advised for Production." +
" Consider workerGid & workerUid options.".warn
);
}
}
}
/**
* This is shorthand for:
* <pre>
* module.workers.forEach(function(worker){...});
* </pre>
*/
function send(){
this.forEach(function(worker){
worker.send.apply(worker, [].slice.apply(arguments));
});
}
function exitGracefully(worker) {
// inform the worker to exit gracefully
worker.send(cservice.msgBus.createMessage("onWorkerStop"));
}