Skip to content

Instantly share code, notes, and snippets.

Created March 21, 2014 19:16
Show Gist options
  • Save anonymous/9693864 to your computer and use it in GitHub Desktop.
Save anonymous/9693864 to your computer and use it in GitHub Desktop.
Main.js Excerpt
var cluster = require('cluster');
var os = require("os");
var hostname = os.hostname();
var IS_MASTER_SHUTTING_DOWN = false;
var numProdCPUs = 12;
var deployment = "prod";
var listenPort = 61337;
require('./classes/service-locator.js');
fs = require('fs');
var domain = require('domain');
ServiceLocator.Process = process;
ServiceLocator.Cluster = cluster;
if(!cluster.isMaster) {
ServiceLocator.WorkerId = cluster.worker.id;
process.on('message', ServiceLocator.Ipc.HandleMessageOnWorker);
ServiceLocator.WorkerId = cluster.worker.id;
var server = ServiceLocator.Restify.createServer( {formatters: {
'text/html': function(req, res, body){
return body;
},
'application/x-gzip': function(req, res, body){
return body;
}
}});
ServiceLocator.Server = server;
server.pre(function(req, res, next) {
var requestDomain = domain.create();
requestDomain.on("error", function(err){
GameLog.warn("REQUEST EXCEPTION: " + err.stack);
try {
if(numProdCPUs > 1){
GameLog.warn("Graceful shutdown starting");
// make sure we close down within 30 seconds
var killtimer = setTimeout(function() {
ServiceLocator.Cluster.worker.destroy(0);
}, 30000);
// But don't keep the process open just for that!
killtimer.unref();
// stop taking new requests.
server.close();
// Let the master know we're dead. This will trigger a
// 'disconnect' in the cluster master, and then it will fork
// a new worker.
ServiceLocator.Cluster.worker.disconnect();
// try to send an error to the request that triggered the problem
res.statusCode = 500;
res.setHeader('content-type', 'text/plain');
res.end('Oops, there was a problem!');
} else{
GameLog.warn("We are only running one one worker, reforking");
res.statusCode = 500;
res.setHeader('content-type', 'text/plain');
res.end('Oops, there was a problem!');
ServiceLocator.Cluster.worker.destroy(1);
}
} catch(err2){
ServiceLocator.Cluster.worker.destroy(1);
}
});
requestDomain.add(req);
requestDomain.add(res);
requestDomain.run(function(){
next();
});
});
server.listen(listenPort, function() {
GameLog.system('Worker thread ' + cluster.worker.id + ' initialized and is listening at ' + server.url);
});
} else{
for (var i = 0; i < numProdCPUs; i++) {
worker = cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
if(signal > 0){
GameLog.error('WORKER ' + worker.process.pid + ' died restarting');
worker = cluster.fork();
worker.on('message', ServiceLocator.Ipc.HandleMessageOnMaster);
} else{
GameLog.error('WORKER reported dead - but didnt ask for a restart');
}
});
cluster.on('disconnect', function(worker) {
GameLog.error('WORKER ' + worker.process.pid + ' disconnected');
if(!IS_MASTER_SHUTTING_DOWN){
worker = cluster.fork();
GameLog.error('REFORKING WORKER ' + worker.process.pid);
worker.on('message', ServiceLocator.Ipc.HandleMessageOnMaster);
}
});
}
if (cluster.isMaster) {
var signals = ['SIGINT', 'SIGTERM', 'SIGQUIT'];
for (i in signals) {
process.on(signals[i], function() {
IS_MASTER_SHUTTING_DOWN = true;
Object.keys(cluster.workers).forEach(function(id) {
cluster.workers[id].destroy(0);
});
process.exit();
})
}
}
function asyncProcess(){
setTimeout(asyncProcess, 500);
try{
ServiceLocator.Ipc.SendMessageToAllWorkers("HealthCheck");
ServiceLocator.RuntimeTool.CheckForNewVersion();
ServiceLocator.Swrve.CheckProcessQueue();
}catch(err){
console.log("caught an error proccessing queue " + err.message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment