-
-
Save Furizaa/c6480fc4b64af8330131 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This script will boot the servers with the number of workers | |
// specified in WORKER_COUNT. | |
// | |
// The master will respond to SIGHUP, which will trigger | |
// restarting all the workers and reloading the app. | |
var cluster = require('cluster'); | |
var chalk = require('chalk'); | |
// Define how many workers to run on the system | |
// Will use all available threads if not specified otherwise. | |
var workerCount = process.env.WORKER_COUNT || require('os').cpus().length; | |
// Hold a list of workers that need to be stopped if a SIGTERM is catched. | |
var workersToStop = []; | |
// Hold a flag that tells us if stopping workers should stay dead. Otherwise | |
// They will be restarted. | |
var stopping = false; | |
// Defines what each worker needs to run | |
// In this case, we run the babel wrapper that starts the http server. | |
cluster.setupMaster({ exec: 'babel.server.js' }); | |
// Easier logging | |
function log(message, worker) { | |
if (worker) { | |
console.log(chalk.cyan('WORKER [', worker.id , ']:'), message); | |
} else { | |
console.log(chalk.yellow('CLUSTER:'), message); | |
} | |
}; | |
// Gets the count of active workers | |
function numWorkers() { | |
return Object.keys(cluster.workers).length; | |
}; | |
// Forks off the workers unless the server is stopping or out pool is full. | |
function forkNewWorkers() { | |
if (!stopping) { | |
for (var i = numWorkers(); i < workerCount; i++) { cluster.fork(); } | |
} | |
}; | |
// Stops a single worker | |
// Gives it 5 seconds to close existing connections before sending TERM. | |
function stopWorker(worker) { | |
log('stopping...', worker); | |
var killTimer = setTimeout(function() { | |
worker.kill(); | |
}, 5000); | |
// Ensure we don't stay up just for this setTimeout | |
killTimer.unref(); | |
worker.disconnect(); | |
worker.on('disconnect', function() { | |
clearTimeout(killTimer); | |
}); | |
}; | |
// Tell the next worker queued to restart to disconnect | |
// This will allow the process to finish it's work | |
// for 60 seconds before sending SIGTERM | |
function stopNextWorker() { | |
var i = workersToStop.pop(); | |
var worker = cluster.workers[i]; | |
if (worker) stopWorker(worker); | |
} | |
// Stops all the works at once | |
function stopAllWorkers() { | |
log('stopping all workers'); | |
stopping = true; | |
for (var id in cluster.workers) { | |
stopWorker(cluster.workers[id]); | |
} | |
} | |
// Worker is now listening on a port | |
// Once it is ready, we can signal the next worker to restart | |
cluster.on('listening', function(worker) { | |
stopNextWorker(); | |
}); | |
// Worker closed down. | |
cluster.on('exit', function(worker) { | |
log('stopped', worker); | |
forkNewWorkers(); | |
}); | |
// Worker started | |
cluster.on('online', function(worker) { | |
log(chalk.green('online', worker.process.pid), worker); | |
}); | |
// HUP signal sent to the master process to start restarting all the workers sequentially | |
process.on('SIGHUP', function() { | |
log('restarting all workers'); | |
workersToStop = Object.keys(cluster.workers); | |
stopNextWorker(); | |
}); | |
// Kill all the workers at once | |
process.on('SIGTERM', stopAllWorkers); | |
// Fork off the initial workers | |
forkNewWorkers(); | |
log('Running on PID ' + chalk.green(process.pid)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment