Comparing version 0.8.1 to 1.0.0
var cluster = require('cluster'), | ||
legacy = require('./legacy'), | ||
path = require('path'), | ||
@@ -53,4 +52,4 @@ RPC = require('./rpc'), | ||
Object.defineProperty(ClusterProcess.prototype, 'isMaster', { | ||
value : cluster.isMaster, | ||
enumerable : true | ||
value: cluster.isMaster, | ||
enumerable: true | ||
}); | ||
@@ -65,4 +64,4 @@ | ||
Object.defineProperty(ClusterProcess.prototype, 'isWorker', { | ||
value : cluster.isWorker, | ||
enumerable : true | ||
value: cluster.isWorker, | ||
enumerable: true | ||
}); | ||
@@ -169,7 +168,7 @@ | ||
var timeouted = extensions.filter(function (name) { | ||
return loadedExtensions.indexOf(name) < 0; | ||
}), | ||
return loadedExtensions.indexOf(name) < 0; | ||
}), | ||
error = LusterClusterProcessError.createError( | ||
LusterClusterProcessError.CODES.EXTENSIONS_LOAD_TIMEOUT, | ||
{ timeouted : timeouted, timeout : loadTimeout }); | ||
{ timeouted: timeouted, timeout: loadTimeout }); | ||
@@ -189,3 +188,3 @@ self.emit('error', error); | ||
if (this._initialized) { | ||
legacy.setImmediate(fn.bind(this)); | ||
setImmediate(fn.bind(this)); | ||
} else { | ||
@@ -210,3 +209,3 @@ this.once('initialized', fn.bind(this)); | ||
LusterClusterProcessError.CODES.REMOTE_COMMAND_ALREADY_REGISTERED, | ||
{ name : name }); | ||
{ name: name }); | ||
} | ||
@@ -244,4 +243,4 @@ | ||
{ | ||
method : 'ClusterProcess#_setupIPCMessagesHandler', | ||
klass : this.constructor.name | ||
method: 'ClusterProcess#_setupIPCMessagesHandler', | ||
klass: this.constructor.name | ||
}); | ||
@@ -268,4 +267,4 @@ }; | ||
{ | ||
name : message.cmd, | ||
klass : this.constructor.name | ||
name: message.cmd, | ||
klass: this.constructor.name | ||
}); | ||
@@ -272,0 +271,0 @@ } else if (typeof message.args === 'undefined') { |
@@ -23,30 +23,26 @@ var util = require('util'), | ||
// path to worker main module | ||
'app' : { required : true, type : 'string' }, | ||
'app': { required: true, type: 'string' }, | ||
// number of workers to spawn | ||
'workers' : { type : 'number' }, | ||
'workers': { type: 'number' }, | ||
// time (in ms) to wait for `online` event from worker | ||
'control.forkTimeout' : { type : 'number' }, | ||
'control.forkTimeout': { type: 'number' }, | ||
// time (in ms) to wait for `exit` event from worker after `disconnect` | ||
'control.stopTimeout' : { type : 'number' }, | ||
'control.stopTimeout': { type: 'number' }, | ||
// if worker dies in `threshold` ms then it's restarts counter increased | ||
'control.exitThreshold' : { type : 'number' }, | ||
'control.exitThreshold': { type: 'number' }, | ||
// allowed restarts before mark worker as dead | ||
'control.allowedSequentialDeaths' : { type : 'number' }, | ||
'control.allowedSequentialDeaths': { type: 'number' }, | ||
// initial port for workers | ||
'server.port' : { type : [ 'number', 'string' ] }, | ||
'server.port': { type: ['number', 'string'] }, | ||
// increase port for every group | ||
'server.groups' : { type : 'number' }, | ||
// every worker has unique debug port (debug.port + worker number) | ||
'debug.port' : { type : 'number' }, | ||
'server.groups': { type: 'number' }, | ||
// hash of extensions; keys – modules' names, values – extensions' configs | ||
'extensions' : { type : 'object' }, | ||
'extensions': { type: 'object' }, | ||
// path to node_modules directory which contains extensions | ||
// configuration directory used by default | ||
'extensionsPath' : { type : 'string' }, | ||
'extensionsPath': { type: 'string' }, | ||
// time to wait for configuration of all extensions | ||
'extensionsLoadTimeout' : { type : 'number' } | ||
'extensionsLoadTimeout': { type: 'number' } | ||
}; | ||
@@ -98,3 +94,3 @@ | ||
LusterConfigurationError.CODES.CAN_NOT_SET_ATOMIC_PROPERTY_FIELD, | ||
{ path : props.slice(0, size).join('.') }); | ||
{ path: props.slice(0, size).join('.') }); | ||
} | ||
@@ -179,3 +175,3 @@ | ||
LusterConfigurationError.CODES.PROP_REQUIRED, | ||
{ property : path }); | ||
{ property: path }); | ||
} else { | ||
@@ -192,5 +188,5 @@ return; | ||
{ | ||
property : path, | ||
type : type, | ||
expected : allowedTypes.join(' or ') | ||
property: path, | ||
type: type, | ||
expected: allowedTypes.join(' or ') | ||
}); | ||
@@ -240,6 +236,6 @@ } | ||
* LUSTER_CONF='server.port=8080' | ||
* # { server : { port : 8080 } } | ||
* # { server: { port: 8080 } } | ||
* | ||
* LUSTER_CONF='app=./worker_debug.js; workers=1' | ||
* # { app : "./worker_debug.js", workers : 1 } | ||
* # { app: "./worker_debug.js", workers : 1 } | ||
* | ||
@@ -250,3 +246,3 @@ * LUSTER_CONF='logStream=' | ||
* LUSTER_CONF='server={"port":8080}' | ||
* # { server : { port : 8080 } } | ||
* # { server: { port: 8080 } } | ||
* | ||
@@ -284,3 +280,3 @@ * @param {Object} config | ||
propValue = JSON.parse(propValue); | ||
} catch(error) { | ||
} catch(error) { // eslint-disable-line no-empty | ||
} | ||
@@ -287,0 +283,0 @@ } |
@@ -11,3 +11,3 @@ var Terror = require('terror'), | ||
{ | ||
ABSTRACT_METHOD_IS_NOT_IMPLEMENTED : | ||
ABSTRACT_METHOD_IS_NOT_IMPLEMENTED: | ||
'Abstract method "%method%" is not implemented in the %klass%' | ||
@@ -23,3 +23,3 @@ }); | ||
{ | ||
ALREADY_READY : | ||
ALREADY_READY: | ||
'Worker#ready() called when worker is is "ready" state already' | ||
@@ -35,11 +35,11 @@ }); | ||
{ | ||
CONFIGURATION_CHECK_FAILED : | ||
CONFIGURATION_CHECK_FAILED: | ||
'Configuration check failed', | ||
PROP_REQUIRED : | ||
PROP_REQUIRED: | ||
'Required property "%property%" is absent', | ||
PROP_TYPE_CHECK_FAILED : | ||
PROP_TYPE_CHECK_FAILED: | ||
'Property "%property%" type is "%type%", but %expected% is expected', | ||
PROP_REGEXP_CHECK_FAILED : | ||
PROP_REGEXP_CHECK_FAILED: | ||
'Property "%property%" doesn\'t meet the regexp "%regexp%"', | ||
CAN_NOT_SET_ATOMIC_PROPERTY_FIELD : | ||
CAN_NOT_SET_ATOMIC_PROPERTY_FIELD: | ||
'Property "%path%" already exists and is not an object' | ||
@@ -55,5 +55,5 @@ }); | ||
{ | ||
INVALID_ATTEMPT_TO_CHANGE_STATE : | ||
INVALID_ATTEMPT_TO_CHANGE_STATE: | ||
'Invalid attempt to change worker #%wid% (pid: %pid%) state from "%state%" to "%targetState%"', | ||
REMOTE_COMMAND_CALL_TO_STOPPED_WORKER : | ||
REMOTE_COMMAND_CALL_TO_STOPPED_WORKER: | ||
'Remote command call "%command%" to stopped worker #%wid%' | ||
@@ -69,7 +69,7 @@ }); | ||
{ | ||
REMOTE_COMMAND_ALREADY_REGISTERED : | ||
REMOTE_COMMAND_ALREADY_REGISTERED: | ||
'Command "%name%" already registered as allowed for remote calls', | ||
REMOTE_COMMAND_IS_NOT_REGISTERED : | ||
REMOTE_COMMAND_IS_NOT_REGISTERED: | ||
'Remote command "%name%" is not registered on %klass%', | ||
EXTENSIONS_LOAD_TIMEOUT : | ||
EXTENSIONS_LOAD_TIMEOUT: | ||
'Extensions %timeouted% not loaded in %timeout% ms' | ||
@@ -85,3 +85,3 @@ }); | ||
{ | ||
REMOTE_CALL_WITH_CALLBACK_TIMEOUT : | ||
REMOTE_CALL_WITH_CALLBACK_TIMEOUT: | ||
'Remote call failed due to timeout for command "%command%"' | ||
@@ -97,5 +97,5 @@ }); | ||
{ | ||
NOT_UNIX_SOCKET : | ||
NOT_UNIX_SOCKET: | ||
'"%value%" is not a unix socket', | ||
CAN_NOT_UNLINK_UNIX_SOCKET : | ||
CAN_NOT_UNLINK_UNIX_SOCKET: | ||
'Can not unlink unix socket "%socketPath%"' | ||
@@ -102,0 +102,0 @@ }); |
@@ -14,3 +14,3 @@ var Objex = require('objex'), | ||
function inspect(val) { | ||
return util.inspect(val, { depth : 1 }).replace(/^\s+/mg, ' ').replace(/\n/g, ''); | ||
return util.inspect(val, { depth: 1 }).replace(/^\s+/mg, ' ').replace(/\n/g, ''); | ||
} | ||
@@ -34,2 +34,2 @@ | ||
module.exports = EventEmitterEx; | ||
module.exports = EventEmitterEx; |
@@ -5,2 +5,2 @@ var cluster = require('cluster'), | ||
module.exports = new Proc(); | ||
module.exports = new Proc(); |
var os = require('os'), | ||
cluster = require('cluster'), | ||
extend = require('extend'), | ||
legacy = require('./legacy'), | ||
ClusterProcess = require('./cluster_process'), | ||
@@ -122,4 +121,4 @@ WorkerWrapper = require('./worker_wrapper'), | ||
alive = workers.reduce(function(count, w) { | ||
return w.dead ? count - 1 : count; | ||
}, workers.length); | ||
return w.dead ? count - 1 : count; | ||
}, workers.length); | ||
@@ -220,3 +219,2 @@ if (alive === 0) { | ||
allowedSequentialDeaths = this.config.get('control.allowedSequentialDeaths'), | ||
debugPort = this.config.get('debug.port'), | ||
@@ -237,19 +235,11 @@ // workers and groups count | ||
// remove `--debug` option from passed to master | ||
this.setup({ | ||
execArgv : process.execArgv.filter(function(s) { | ||
return ! /^\-\-debug/.test(s); | ||
}) | ||
}); | ||
// create pool of workers | ||
while (count > i++) { | ||
this.add(new WorkerWrapper(this, { | ||
forkTimeout : forkTimeout, | ||
stopTimeout : stopTimeout, | ||
exitThreshold : exitThreshold, | ||
allowedSequentialDeaths : allowedSequentialDeaths, | ||
debugPort : debugPort && debugPort + i - 1, | ||
port : isServerPortSet ? port.next(group) : 0, | ||
_maxListeners : this._maxListeners | ||
forkTimeout: forkTimeout, | ||
stopTimeout: stopTimeout, | ||
exitThreshold: exitThreshold, | ||
allowedSequentialDeaths: allowedSequentialDeaths, | ||
port: isServerPortSet ? port.next(group) : 0, | ||
_maxListeners: this._maxListeners | ||
})); | ||
@@ -294,3 +284,3 @@ | ||
} else { | ||
legacy.setImmediate(callback.bind(self)); | ||
setImmediate(callback.bind(self)); | ||
} | ||
@@ -420,4 +410,3 @@ | ||
*/ | ||
Master.prototype.remoteCallToAll = function(name) { | ||
/* jshint unused:false */ | ||
Master.prototype.remoteCallToAll = function(name) { // eslint-disable-line no-unused-vars | ||
var args = Array.prototype.slice.call(arguments, 0); | ||
@@ -424,0 +413,0 @@ |
@@ -29,3 +29,3 @@ var fs = require('fs'), | ||
Object.defineProperty(this, 'family', { | ||
get : function() { | ||
get: function() { | ||
return isUnixSocket(this.value) ? Port.UNIX : Port.INET; | ||
@@ -49,4 +49,4 @@ } | ||
Object.defineProperty(Port, family, { | ||
value : family.toLowerCase(), | ||
enumerable : true | ||
value: family.toLowerCase(), | ||
enumerable: true | ||
}); | ||
@@ -106,3 +106,3 @@ }); | ||
.createError(LusterPortError.CODES.NOT_UNIX_SOCKET) | ||
.bind({ value : value })); | ||
.bind({ value: value })); | ||
return; | ||
@@ -115,3 +115,3 @@ } | ||
.createError(LusterPortError.CODES.CAN_NOT_UNLINK_UNIX_SOCKET, err) | ||
.bind({ socketPath : value })); | ||
.bind({ socketPath: value })); | ||
return; | ||
@@ -118,0 +118,0 @@ } |
@@ -1,8 +0,7 @@ | ||
var legacy = require('./legacy'), | ||
LusterRPCCallbackError = require('./errors').LusterRPCCallbackError; | ||
var LusterRPCCallbackError = require('./errors').LusterRPCCallbackError; | ||
var RPCCallback = { | ||
_storage : {}, | ||
_storage: {}, | ||
_counter : 0, | ||
_counter: 0, | ||
@@ -16,3 +15,3 @@ /** | ||
*/ | ||
setCallback : function(proc, command, callback, timeout) { | ||
setCallback: function(proc, command, callback, timeout) { | ||
var self = this, | ||
@@ -28,4 +27,4 @@ storage = self._storage; | ||
storage[callbackId] = { | ||
callback : callback, | ||
timeout : | ||
callback: callback, | ||
timeout: | ||
setTimeout(function() { | ||
@@ -36,3 +35,3 @@ storage[callbackId].callback( | ||
LusterRPCCallbackError.CODES.REMOTE_CALL_WITH_CALLBACK_TIMEOUT, | ||
{ command : command })); | ||
{ command: command })); | ||
self.removeCallback(callbackId); | ||
@@ -50,3 +49,3 @@ }, timeout) | ||
*/ | ||
processCallback : function(proc, callbackId, data) { | ||
processCallback: function(proc, callbackId, data) { | ||
var stored = this._storage[callbackId]; | ||
@@ -58,3 +57,3 @@ | ||
legacy.setImmediate(function() { | ||
setImmediate(function() { | ||
stored.callback(proc, null, data); | ||
@@ -68,3 +67,3 @@ }); | ||
*/ | ||
removeCallback : function(callbackId) { | ||
removeCallback: function(callbackId) { | ||
var timeout = this._storage[callbackId].timeout; | ||
@@ -71,0 +70,0 @@ |
@@ -9,5 +9,5 @@ /** | ||
*/ | ||
createCaller : function(target) { | ||
createCaller: function(target) { | ||
return function(name) { | ||
var message = { cmd : 'luster_' + name }; | ||
var message = { cmd: 'luster_' + name }; | ||
@@ -32,3 +32,3 @@ if (arguments.length > 1) { | ||
*/ | ||
parseMessage : function(message) { | ||
parseMessage: function(message) { | ||
if (message && | ||
@@ -39,4 +39,4 @@ typeof message.cmd === 'string' && | ||
return /** @type IPCMessage */{ | ||
cmd : message.cmd.substr(7), | ||
args : message.args | ||
cmd: message.cmd.substr(7), | ||
args: message.args | ||
}; | ||
@@ -51,11 +51,11 @@ } else { | ||
*/ | ||
fns : { | ||
worker : { | ||
broadcastMasterEvent : 'core.worker.broadcastMasterEvent', | ||
applyForeignProperties : 'core.worker.applyForeignProperties' | ||
fns: { | ||
worker: { | ||
broadcastMasterEvent: 'core.worker.broadcastMasterEvent', | ||
applyForeignProperties: 'core.worker.applyForeignProperties' | ||
}, | ||
master : { | ||
broadcastWorkerEvent : 'core.master.broadcastWorkerEvent' | ||
master: { | ||
broadcastWorkerEvent: 'core.master.broadcastWorkerEvent' | ||
}, | ||
callback : 'core.callback' | ||
callback: 'core.callback' | ||
} | ||
@@ -62,0 +62,0 @@ }; |
var cluster = require('cluster'), | ||
legacy = require('./legacy'), | ||
RPC = require('./rpc'), | ||
@@ -38,3 +37,2 @@ RPCCallback = require('./rpc-callback'), | ||
* How many times worker can die in `exitThreshold` time before will be marked as dead. | ||
* @property {Number} [debugPort=0] | ||
*/ | ||
@@ -80,21 +78,10 @@ | ||
this.options = { | ||
persistent : typeof options.persistent === 'undefined' ? true : options.persistent, | ||
forkTimeout : options.forkTimeout, | ||
stopTimeout : options.stopTimeout, | ||
exitThreshold : options.exitThreshold, | ||
allowedSequentialDeaths : options.allowedSequentialDeaths || 0 | ||
persistent: typeof options.persistent === 'undefined' ? true : options.persistent, | ||
forkTimeout: options.forkTimeout, | ||
stopTimeout: options.stopTimeout, | ||
exitThreshold: options.exitThreshold, | ||
allowedSequentialDeaths: options.allowedSequentialDeaths || 0 | ||
}; | ||
/** | ||
* Valid debug port number or `false`. | ||
* @memberOf WorkerWrapper#options | ||
* @property {Number|Boolean} debugPort | ||
* @readonly | ||
* @public | ||
*/ | ||
Object.defineProperty(this.options, 'debugPort', { | ||
value : typeof options.debugPort === 'number' ? options.debugPort : false | ||
}); | ||
/** | ||
* Setter of `this.options.port` affects value of the `isListeningUnixSocket` property. | ||
@@ -106,6 +93,6 @@ * @memberOf WorkerWrapper#options | ||
Object.defineProperty(this.options, 'port', { | ||
get : function() { | ||
get: function() { | ||
return _port; | ||
}, | ||
set : function(value) { | ||
set: function(value) { | ||
if ( ! (value instanceof Port)) { | ||
@@ -115,6 +102,5 @@ value = new Port(value); | ||
/* jshint boss:true */ | ||
return _port = value; | ||
}, | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -131,4 +117,4 @@ | ||
Object.defineProperty(this, 'wid', { | ||
value : ++nextId, | ||
enumerable : true | ||
value: ++nextId, | ||
enumerable: true | ||
}); | ||
@@ -143,6 +129,6 @@ | ||
Object.defineProperty(this, 'pid', { | ||
get : function() { | ||
get: function() { | ||
return this.process.pid; | ||
}, | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -159,6 +145,6 @@ | ||
Object.defineProperty(this, 'state', { | ||
get : function() { | ||
get: function() { | ||
return _state; | ||
}, | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -263,3 +249,3 @@ | ||
WorkerWrapper.broadcastWorkerEvent = function(worker, event) { | ||
var args = [ 'received worker ' + event, worker ], | ||
var args = ['received worker ' + event, worker], | ||
i = 2, | ||
@@ -286,9 +272,9 @@ len = arguments.length; | ||
Object.defineProperty(WorkerWrapper, 'STATES', { | ||
value : Object.freeze({ | ||
STOPPED : 'stopped', | ||
LAUNCHING : 'launching', | ||
RUNNING : 'running', | ||
STOPPING : 'stopping' | ||
value: Object.freeze({ | ||
STOPPED: 'stopped', | ||
LAUNCHING: 'launching', | ||
RUNNING: 'running', | ||
STOPPING: 'stopping' | ||
}), | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -298,7 +284,4 @@ | ||
* @private | ||
* @param {Number} code Exit code | ||
* @param {String} [signal] Signal received by worker which leads to suicide | ||
*/ | ||
WorkerWrapper.prototype._onExit = function(code, signal) { | ||
/*jshint unused:false*/ | ||
WorkerWrapper.prototype._onExit = function() { | ||
this.ready = false; | ||
@@ -331,4 +314,4 @@ this._setState(WorkerWrapper.STATES.STOPPED); | ||
this.remoteCall(RPC.fns.worker.applyForeignProperties, { | ||
wid : this.wid, | ||
pid : this.process.pid | ||
wid: this.wid, | ||
pid: this.process.pid | ||
}); | ||
@@ -386,13 +369,3 @@ }; | ||
WorkerWrapper.prototype._onStateStopping = function() { | ||
var self = this; | ||
if (this.options.stopTimeout) { | ||
this.stopTimeout = setTimeout(function() { | ||
self.stopTimeout = null; | ||
if (self._worker !== null) { | ||
self._worker.kill(); | ||
} | ||
}, this.options.stopTimeout); | ||
} | ||
this._scheduleForceStop(); | ||
}; | ||
@@ -405,7 +378,3 @@ | ||
WorkerWrapper.prototype._onStateStopped = function() { | ||
// clear stopTimeout | ||
if (this.stopTimeout) { | ||
clearTimeout(this.stopTimeout); | ||
this.stopTimeout = null; | ||
} | ||
this._cancelForceStop(); | ||
@@ -430,3 +399,3 @@ // increase sequential deaths count if worker life time less | ||
if (((this.options.persistent && ! this.stopping) || this.restarting) && ! this.dead) { | ||
legacy.setImmediate(this.run.bind(this)); | ||
setImmediate(this.run.bind(this)); | ||
} | ||
@@ -445,4 +414,4 @@ | ||
Object.defineProperty(WorkerWrapper, '_PROXY_EVENTS', { | ||
value : Object.freeze([ 'message', 'online', 'listening', 'disconnect', 'exit' ]), | ||
enumerable : true | ||
value: Object.freeze(['message', 'online', 'listening', 'disconnect', 'exit']), | ||
enumerable: true | ||
}); | ||
@@ -458,3 +427,3 @@ | ||
Object.defineProperty(WorkerWrapper, '_RPC_EVENTS', { | ||
value : Object.freeze([ | ||
value: Object.freeze([ | ||
'configured', | ||
@@ -466,3 +435,3 @@ 'extension loaded', | ||
]), | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -477,8 +446,8 @@ | ||
Object.defineProperty(WorkerWrapper, 'EVENTS', { | ||
value : Object.freeze( | ||
[ 'error', 'state', 'fork' ] | ||
value: Object.freeze( | ||
['error', 'state', 'fork'] | ||
.concat(WorkerWrapper._PROXY_EVENTS) | ||
.concat(WorkerWrapper._RPC_EVENTS) | ||
), | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -510,7 +479,7 @@ | ||
LusterWorkerWrapperError.CODES.INVALID_ATTEMPT_TO_CHANGE_STATE, | ||
{/*jshint indent:false*/ | ||
wid : this.wid, | ||
pid : this.process.pid, | ||
state : this.state, | ||
targetState : WorkerWrapper.STATES.LAUNCHING | ||
{ | ||
wid: this.wid, | ||
pid: this.process.pid, | ||
state: this.state, | ||
targetState: WorkerWrapper.STATES.LAUNCHING | ||
})); | ||
@@ -523,20 +492,8 @@ | ||
legacy.setImmediate(function() { | ||
var debugPort = self.options.debugPort; | ||
// Set individual debug ports for each worker. | ||
// For port number generation and assignment look for `Master#run` method. | ||
if (debugPort) { | ||
cluster.settings.execArgv.push('--debug=' + debugPort); | ||
} | ||
setImmediate(function() { | ||
/** @private */ | ||
self._worker = cluster.fork({ | ||
port : self.options.port | ||
port: self.options.port | ||
}); | ||
if (debugPort) { | ||
cluster.settings.execArgv.pop(); | ||
} | ||
/** @private */ | ||
@@ -562,7 +519,7 @@ self._remoteCall = RPC.createCaller(self._worker); | ||
LusterWorkerWrapperError.CODES.INVALID_ATTEMPT_TO_CHANGE_STATE, | ||
{/*jshint indent:false*/ | ||
wid : this.wid, | ||
pid : this.process.pid, | ||
state : this.state, | ||
targetState : WorkerWrapper.STATES.STOPPING | ||
{ | ||
wid: this.wid, | ||
pid: this.process.pid, | ||
state: this.state, | ||
targetState: WorkerWrapper.STATES.STOPPING | ||
})); | ||
@@ -577,6 +534,7 @@ | ||
legacy.setImmediate(function() { | ||
setImmediate(function() { | ||
// state can be changed before function call | ||
if (self.isRunning()) { | ||
self._worker.disconnect(); | ||
self._scheduleForceStop(); | ||
} | ||
@@ -610,6 +568,6 @@ }); | ||
LusterWorkerWrapperError.CODES.REMOTE_COMMAND_CALL_TO_STOPPED_WORKER, | ||
{/*jshint indent:false*/ | ||
wid : this.wid, | ||
pid : this.process.pid, | ||
command : name | ||
{ | ||
wid: this.wid, | ||
pid: this.process.pid, | ||
command: name | ||
})); | ||
@@ -620,8 +578,8 @@ } | ||
// proxy some properties to WorkerWrapper#_worker | ||
[ 'id', 'process', 'suicide' ].forEach(function(propName) { | ||
['id', 'process', 'suicide'].forEach(function(propName) { | ||
Object.defineProperty(WorkerWrapper.prototype, propName, { | ||
get : function() { | ||
get: function() { | ||
return this._worker[propName]; | ||
}, | ||
enumerable : true | ||
enumerable: true | ||
}); | ||
@@ -631,3 +589,3 @@ }); | ||
// proxy some methods to WorkerWrapper#_worker | ||
[ 'send', 'disconnect' ].forEach(function(methodName) { | ||
['send', 'disconnect'].forEach(function(methodName) { | ||
WorkerWrapper.prototype[methodName] = function() { | ||
@@ -672,2 +630,34 @@ this._worker[methodName].apply(this._worker, arguments); | ||
/** | ||
* Schedule a forceful worker stop using signal. | ||
* Only schedules timeout if it was not set yet. | ||
* @private | ||
*/ | ||
WorkerWrapper.prototype._scheduleForceStop = function() { | ||
// We could schedule force stop either when `stop` method is called or when `disconnected` event received from | ||
// worker. In most cases `stop` will be called and then `disconnected` event will fire, therefore we shall | ||
// make sure we do not re-run the force stop timer. | ||
if (this.options.stopTimeout && ! this.stopTimeout) { | ||
var self = this; | ||
this.stopTimeout = setTimeout(function() { | ||
self.stopTimeout = null; | ||
if (self._worker !== null) { | ||
self._worker.process.kill(); | ||
} | ||
}, this.options.stopTimeout); | ||
} | ||
}; | ||
/** | ||
* Clears a forceful worker stop. | ||
* @private | ||
*/ | ||
WorkerWrapper.prototype._cancelForceStop = function() { | ||
if (this.stopTimeout) { | ||
clearTimeout(this.stopTimeout); | ||
this.stopTimeout = null; | ||
} | ||
}; | ||
module.exports = WorkerWrapper; |
@@ -6,3 +6,2 @@ var cluster = require('cluster'), | ||
LusterWorkerError = require('./errors').LusterWorkerError, | ||
legacy = require('./legacy'), | ||
Worker; | ||
@@ -26,4 +25,4 @@ | ||
Object.defineProperty(this, 'id', { | ||
value : cluster.worker.id, | ||
enumerable : true | ||
value: cluster.worker.id, | ||
enumerable: true | ||
}); | ||
@@ -52,3 +51,3 @@ | ||
Worker.prototype.broadcastMasterEvent = function(proc, emitArgs) { | ||
var args = [ 'master ' + emitArgs[0] ].concat(emitArgs.slice(1)); | ||
var args = ['master ' + emitArgs[0]].concat(emitArgs.slice(1)); | ||
this.emit.apply(this, args); | ||
@@ -63,5 +62,4 @@ }; | ||
*/ | ||
Worker.prototype._broadcastEvent = function(event) { | ||
/* jshint unused:false */ | ||
var args = [ RPC.fns.master.broadcastWorkerEvent ], | ||
Worker.prototype._broadcastEvent = function(event) { // eslint-disable-line no-unused-vars | ||
var args = [RPC.fns.master.broadcastWorkerEvent], | ||
i = 0, | ||
@@ -86,4 +84,4 @@ len = arguments.length; | ||
Object.defineProperty(this, propName, { | ||
value : props[propName], | ||
enumerable : true | ||
value: props[propName], | ||
enumerable: true | ||
}); | ||
@@ -100,3 +98,3 @@ }, this); | ||
if (this._foreignPropertiesReceived) { | ||
legacy.setImmediate(fn.bind(this)); | ||
setImmediate(fn.bind(this)); | ||
} else { | ||
@@ -125,3 +123,3 @@ this.once('foreign properties received', fn.bind(this)); | ||
if ( ! this.config.get('control.triggerReadyStateManually', false)) { | ||
legacy.setImmediate(this.ready.bind(this)); | ||
setImmediate(this.ready.bind(this)); | ||
} | ||
@@ -128,0 +126,0 @@ |
104
package.json
{ | ||
"name" : "luster", | ||
"version" : "0.8.1", | ||
"description" : "Node.js cluster wrapper", | ||
"main" : "./lib/luster.js", | ||
"bin" : { | ||
"luster" : "./bin/luster.js" | ||
}, | ||
"scripts": { | ||
"lint": "./node_modules/.bin/jshint --config ./.jshintrc ./lib && ./node_modules/.bin/jscs ./lib", | ||
"unit": "istanbul test _mocha -- --recursive test/", | ||
"test": "npm run lint && npm run unit" | ||
}, | ||
"repository" : { | ||
"type" : "git", | ||
"url" : "git://github.com/nodules/luster.git" | ||
}, | ||
"keywords" : [ | ||
"cluster", | ||
"luster", | ||
"ipc" | ||
], | ||
"author" : "Phillip Kovalev <twilightfeel@gmail.com> (https://github.com/kaero)", | ||
"maintainers" : [ | ||
"Phillip Kovalev <twilightfeel@gmail.com> (https://github.com/kaero)" | ||
], | ||
"contributors" : [ | ||
"Vladimir Varankin <nek.narqo@gmail.com> (https://github.com/narqo)", | ||
"Alexey Rybakov <alexrybakov@yandex.ru> (https://github.com/flackus)" | ||
], | ||
"licenses" : [ | ||
{ | ||
"type" : "MIT", | ||
"url" : "http://github.com/nodules/luster/raw/master/LICENSE" | ||
} | ||
], | ||
"readmeFilename" : "README.md", | ||
"dependencies" : { | ||
"objex" : "^0.4.1", | ||
"terror" : "^1.0.0", | ||
"extend": "^3.0.0" | ||
}, | ||
"devDependencies" : { | ||
"chai": "^3.5.0", | ||
"jshint" : "^2.1.0", | ||
"jscs" : "^1.13.0", | ||
"istanbul": "^0.4.1", | ||
"mocha": "^3.1.2", | ||
"sinon": "^1.17.6", | ||
"sinon-chai": "^2.8.0" | ||
}, | ||
"engines" : { | ||
"node" : ">=0.8" | ||
"name": "luster", | ||
"version": "1.0.0", | ||
"description": "Node.js cluster wrapper", | ||
"main": "./lib/luster.js", | ||
"bin": { | ||
"luster": "./bin/luster.js" | ||
}, | ||
"scripts": { | ||
"lint": "eslint ./lib ./test ./examples", | ||
"unit": "istanbul test _mocha -- test/unit/test", | ||
"func": "mocha test/func/test", | ||
"test": "npm run lint && npm run unit && npm run func" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/nodules/luster.git" | ||
}, | ||
"keywords": [ | ||
"cluster", | ||
"luster", | ||
"ipc" | ||
], | ||
"author": "Phillip Kovalev <twilightfeel@gmail.com> (https://github.com/kaero)", | ||
"maintainers": [ | ||
"Phillip Kovalev <twilightfeel@gmail.com> (https://github.com/kaero)" | ||
], | ||
"contributors": [ | ||
"Vladimir Varankin <nek.narqo@gmail.com> (https://github.com/narqo)", | ||
"Alexey Rybakov <alexrybakov@yandex.ru> (https://github.com/flackus)" | ||
], | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "http://github.com/nodules/luster/raw/master/LICENSE" | ||
} | ||
], | ||
"dependencies": { | ||
"extend": "^3.0.0", | ||
"objex": "^0.4.1", | ||
"terror": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"eslint": "^3.15.0", | ||
"eslint-config-nodules": "^0.4.0", | ||
"istanbul": "^0.4.1", | ||
"mocha": "^3.1.2", | ||
"sinon": "^1.17.6", | ||
"sinon-chai": "^2.8.0" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
Luster [![NPM version][npm-image]][npm-link] | ||
Luster [![NPM version][npm-image]][npm-link] [![Build status][build-image]][build-link] | ||
====== | ||
@@ -12,3 +12,2 @@ | ||
* Maintains specified quantity of running workers. | ||
* Allocates separate ports for debugging workers in the cluster. | ||
* Runs groups of workers on the different ports for 3rd party load balancing (nginx or haproxy, for example). | ||
@@ -19,2 +18,6 @@ * Allows configuration via JSON, JS or anything that can be `require`d out of the box. | ||
## Node.js versions support | ||
In `luster@1.0.0` we dropped support for `node<4`. | ||
If you desperately need to make it run on older `node` versions, use `luster@0.8.1`. | ||
## Quick start | ||
@@ -118,11 +121,2 @@ | ||
debug : { | ||
// debug port for first worker; each following will | ||
// use previous worker port + 1 | ||
// | ||
// deprecated: this option doesn't work with Node.js 0.12+ | ||
// and might be removed in future major versions | ||
port : 5010 | ||
}, | ||
// extensions to load | ||
@@ -169,6 +163,4 @@ // each key in the "extensions" hash is a npm module name | ||
Extensions is a simple Node.js module, which must export object with `configure` function, | ||
which will be called duering master and worker configuration. | ||
which will be called during master and worker configuration. | ||
> @todo | ||
Synchronous extension initialization: | ||
@@ -234,2 +226,4 @@ ```javascript | ||
[devdeps-link]: https://david-dm.org/nodules/luster#info=devDependencies | ||
[build-image]: https://travis-ci.org/nodules/luster.svg?branch=master | ||
[build-link]: https://travis-ci.org/nodules/luster | ||
@@ -236,0 +230,0 @@ ## Debuggability |
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
199170
28
2533
1
234