Skip to content

Instantly share code, notes, and snippets.

@sansmischevia
Created April 3, 2013 07:26
Show Gist options
  • Save sansmischevia/5299114 to your computer and use it in GitHub Desktop.
Save sansmischevia/5299114 to your computer and use it in GitHub Desktop.
basic cluster bootloader
var cluster = require('cluster'),
os = require('os'),
http = require('http');
// List of 'active' workers:
var workers = [];
var start_count = 0;
// The amount of time we wait before killing a process during a reload:
var DEATH_TIMEOUT = 60000; // 1 minute
var RESTART_TIMEOUT = 50400000; // 14 hours
// Initialize the interval logic
var interval_id;
function startInterval() {
clearInterval(interval_id);
interval_id = setInterval(function () {
console.log("No recent deploys. Restarting...");
process.kill(process.pid, "SIGUSR2");
}, RESTART_TIMEOUT);
}
if (cluster.isMaster) {
os.cpus().forEach(function() {
workers.push(cluster.fork());
});
startInterval();
process.on('SIGUSR2',function() {
console.log("Received SIGUSR2 with " + workers.length + " workers running");
console.log("Restart #" + (++start_count));
startInterval();
// Blank the worker list, but keep a copy for ourselves:
var workers_copy = workers.slice();
workers = [];
workers_copy.forEach(function (worker) {
console.log("Disconnecting worker ID " + worker.id);
worker.disconnect();
// Timeout, just in case it won't die willingly:
var savedTimeout = setTimeout(function () {
console.log("Worker ID " + worker.id + " not responding. Killing process...");
worker.forced_death = true;
worker.destroy();
}, DEATH_TIMEOUT);
// Worker will raise a disconnect event if it runs through its queue gracefully:
worker.on('disconnect', function () {
// Check to see if disconnect is raised because of a force kill:
if (worker.forced_death) { return; }
// Else, we just ran through our connections. Cool!
console.log("Worker ID " + worker.id + " ran through connections gracefully.");
worker.destroy();
clearTimeout(savedTimeout);
});
// Push this worker's replacement into the new worker list:
workers.push(cluster.fork());
});
});
cluster.on('exit', function(worker, code, signal) {
// Suicide is if we're the ones who killed it:
if (worker.suicide) { return; }
// Else, this shouldn't have died. Restart:
workers = workers.filter(function(w) { return w.id !== worker.id; });
if (!worker.reloaded) {
console.log('Worker ' + worker.id + ' died, forking a replacement');
workers.push(cluster.fork());
}
});
} else {
var server = require('./app');
server.listen(3000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment