Skip to content
This repository was archived by the owner on Feb 27, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ clusterMaster.quit()

// not so graceful shutdown
clusterMaster.quitHard()

// listen to events to additional cleanup or shutdown
clusterMaster.emitter()
.on('resize', function (clusterSize) { })
.on('restart', function () { })
.on('quit', function () { })
.on('quitHard', function () { });
```

## Methods
Expand All @@ -57,19 +64,29 @@ clusterMaster.quitHard()

Set the cluster size to `n`. This will disconnect extra nodes and/or
spin up new nodes, as needed. Done by default on restarts.
Fires `resize` event with new clusterSize just before performing the
resize.

### clusterMaster.restart(cb)

One by one, shut down nodes and spin up new ones. Callback is called
when finished.
when finished. Fires `restart` event just before performing restart.

### clusterMaster.quit()

Gracefully shut down the worker nodes and then process.exit(0).
Fires `quit` event just before performing the shutdown.

### clusterMaster.quitHard()

Forcibly shut down the worker nodes and then process.exit(1).
Fires `quitHard` event just before performing hard shut down.

### clusterMaster.emitter()

Retrieve the clusterMaster EventEmitter to be able to listen
to clusterMaster events. This emitter is also returned from
the original clusterMaster() constructor.

## Configs

Expand All @@ -89,3 +106,14 @@ The `exec`, `env`, `argv`, and `silent` configs are passed to the
the parent. Called in the context of the worker, so you can reply by
looking at `this`.

## Events

clusterMaster emits events on clusterMaster.emitter() when its methods
are called which allows you to respond and do additional cleanup right
before the action is carried out.

* `resize` - fired on clusterMaster.resize(n), listener ex: fn(clusterSize)
* `restart` - fired on clusterMaster.restart(), listener ex: fn(oldWorkers)
`restartComplete` - fired when restart is completed
* `quit` - fired on clusterMaster.quit()
* `quitHard` - fired on clusterMaster.quitHard()
63 changes: 53 additions & 10 deletions cluster-master.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ var cluster = require("cluster")
, onmessage
, repl = require('repl')
, net = require('net')
, EventEmitter = require('events').EventEmitter
, masterEmitter = new EventEmitter()
, fs = require('fs')
, util = require('util')

exports = module.exports = clusterMaster
exports.restart = restart
exports.resize = resize
exports.quitHard = quitHard
exports.quit = quit
exports.emitter = emitter
exports.restart = emitAndRestart
exports.resize = emitAndResize
exports.quitHard = emitAndQuitHard
exports.quit = emitAndQuit

var debugStreams = {}
function debug () {
Expand Down Expand Up @@ -77,6 +80,8 @@ function clusterMaster (config) {
// now make it the right size
debug('resize and then setup repl')
resize(setupRepl)

return masterEmitter
}

function select (field) {
Expand Down Expand Up @@ -126,9 +131,10 @@ function setupRepl () {
})
var context = {
repl: r,
resize: resize,
restart: restart,
quit: quit,
resize: emitAndResize,
restart: emitAndRestart,
quit: emitAndQuit,
quitHard: emitAndQuitHard,
cluster: cluster,
get size () {
return clusterSize
Expand Down Expand Up @@ -412,9 +418,9 @@ function quit () {

function setupSignals () {
try {
process.on("SIGHUP", restart)
process.on("SIGINT", quit)
process.on("SIGKILL", quitHard)
process.on("SIGHUP", emitAndRestart)
process.on("SIGINT", emitAndQuit)
process.on("SIGKILL", emitAndQuitHard)
} catch (e) {
// Must be on Windows, waaa-waaah.
}
Expand All @@ -423,3 +429,40 @@ function setupSignals () {
if (!quitting) quitHard()
})
}

function emitter() {
return masterEmitter
}

function emitAndResize(n) {
masterEmitter.emit('resize', n)
process.nextTick(function () { resize(n) })
}

function emitAndRestart(cb) {
if (restarting) {
debug("Already restarting. Cannot restart yet.")
return
}
var currentWorkers = Object.keys(cluster.workers).reduce(function (accum, k) {
accum[k] = { pid: cluster.workers[k].pid };
return accum;
}, {});
masterEmitter.emit('restart', currentWorkers);
process.nextTick(function () {
restart(function () {
masterEmitter.emit('restartComplete');
if (cb) cb();
});
});
}

function emitAndQuit() {
masterEmitter.emit('quit')
process.nextTick(function () { quit() })
}

function emitAndQuitHard() {
masterEmitter.emit('quitHard')
process.nextTick(function () { quitHard() })
}