indexzero
1/11/2012 - 7:59 PM

clustering with node 0.6.7

clustering with node 0.6.7

global.config = require('./lib/config').load("config/app.json");
var cluster = require('cluster');
var fs = require('fs');
var app = require('./app');

// Logging
var log = require('./lib/winston');
global.log = log;

// Write out pidfile
var pidfile = fs.openSync(__dirname + "/pids/master.pid", "w");
fs.writeSync(pidfile, process.pid + "");
fs.closeSync(pidfile);

var numWorkers = 2;

if (cluster.isMaster) {
  log.notice(config.name + " starting in " + config.env + " mode on http://127.0.0.1:" + config.port);
  process.title = "cluster master";

  // Fork workers.
  var workers = [];
  for (var i = 0; i < numWorkers; i++) {
    workers.push(cluster.fork());
  }

  // Restart our workers if they die
  cluster.on('death', function(worker) {
    log.crit('worker ' + worker.pid + ' died, restarting.');
    cluster.fork();
  });

  // Kill the old master process if it was reloaded
  if(process.env['OLD_NODE']) {
    setTimeout(function() {
      // process.kill(process.env['OLD_NODE'], 'SIGQUIT');
    }, 2000);
  }

  var gracefulRestart = function() {
    for(worker in workers) {
      workers[worker].on('message', function(msg) {
        if(msg.childfinished) {
          numWorkers--;
          if(numWorkers == 0) { process.exit(0); }
        }
      });

      workers[worker].kill('SIGQUIT');
    }

    setTimeout(function() {
      log.error("Timing out with " + numWorkers + " workers still not finished.");
      process.exit(0);
    }, 30000);
  };

  var hardRestart = function() {
    for(worker in workers) {
      workers[worker].kill();
    }

    process.exit(0);
  };

  var reload = function() {
    var newEnvironment = process.env;
    newEnvironment['OLD_NODE'] = process.pid;
    var newServer = require('child_process').fork(__filename, [], { cwd: process.cwd(),
                                                                    env: newEnvironment,
                                                                    setsid: false });
  };

  process.on('SIGQUIT', gracefulRestart);
  process.on('SIGINT', hardRestart);
  process.on('SIGUSR2', reload);
} else {
  log.notice("forked worker " + process.pid);
  process.title = "cluster worker";

  app.listen(config.port);

  var gracefulShutdown = function() {
    app.on('close', function() {
      process.send({ childfinished: true });
      setTimeout(function() {
        process.exit(0);
      }, 1000);
    });

    app.close();

  };

  process.on('SIGQUIT', gracefulShutdown);
}