Skip to content

Instantly share code, notes, and snippets.

@jfensign
Created February 7, 2014 05:41
Show Gist options
  • Save jfensign/8857862 to your computer and use it in GitHub Desktop.
Save jfensign/8857862 to your computer and use it in GitHub Desktop.
Generic Node.js cluster implementation.
var Cluster = require('cluster')
//Console Styling
, Colors = require('colors')
//Total number of CPUs
, CPU_Count = require('os').cpus().length
//Timeouts for handling erroneous child-process spawning
, TimeOuts = []
//Number of worker processes
, WorkerC = 0
//Log errors (an alert/logging mechanism belongs here)
, LogError = function(e) {
console.log(e.stack);
}
//Server file
, Server = require("./Server")
//Called when a child-process fails to start
, onTimeout = function() {
console.log("%s", "Unable to start child process." .red);
process.exit(1);
}
//Create a worker
, newWorker = function() {
Cluster.fork();
WorkerC++;
return;
}
//Kill a worker
, killWorker = function(worker, code, signal, cb) {
clearTimeout(TimeOuts[worker.id]);
WorkerC--;
console.log("Worker %s killed by:\nPOSIX: %s\nREPL Code: %s" .red
, worker.id
, (signal || null)
, (code || null));
return cb();
};
/*
* Handle Master Process *
*/
if(Cluster.isMaster) {
do {
if(WorkerC === 0)
console.log("%d CPUs available.".blue, CPU_Count);
newWorker();
if(WorkerC === CPU_Count-1)
console.log("Application state changed from %s to %s", "Starting".yellow, "Started".green);
} while (WorkerC < CPU_Count-1); //Leave a CPU available for ad-hoc jobs in application
/*
* Cluster Events *
*/
Cluster
.on('fork', function(worker) {
TimeOuts[worker.id] = setTimeout(onTimeout, 2000);
})
.on('online', function(worker) {
clearTimeout(TimeOuts[worker.id]);
console.log("Worker %s with PID %s started".yellow
, worker.id
, worker.process.pid);
})
.on('listening', function(worker, address) {
console.log("Worker %s with PID %s bound to: %s:%s".green
, worker.id
, worker.process.pid
, address.address
, address.port);
})
.on('disconnect', function(worker, code, signal) {
console.log("Worker %s with PID %s killed\ncode: %s\nsignal: %s".green
, worker.id
, worker.process.pid
, code
, signal);
})
.on('exit', function(worker, code, signal) {
killWorker(worker, code, signal, newWorker);
});
}
else {
/*
* Handle Child Processes *
*/
if(Cluster.isWorker) {
/*
* Instantiate App Server *
*/
var
server = new Server();
/*
* Listen for Requests (assumes server has a listen method)*
*/
server.listen();
/*
* Server Events *
*/
server.on('clientError', LogError);
/*
* Process Events *
*/
process.on('uncaughtException', LogError);
process.on('exit', LogError);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment