cluster: support options in Worker constructor
This commit moves some common Worker code into the constructor via support for an options argument. Reviewed-By: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
parent
4b59db008c
commit
d287b8e58a
@ -35,12 +35,24 @@ cluster.isWorker = ('NODE_UNIQUE_ID' in process.env);
|
|||||||
cluster.isMaster = (cluster.isWorker === false);
|
cluster.isMaster = (cluster.isWorker === false);
|
||||||
|
|
||||||
|
|
||||||
function Worker() {
|
function Worker(options) {
|
||||||
if (!(this instanceof Worker)) return new Worker;
|
if (!(this instanceof Worker))
|
||||||
|
return new Worker(options);
|
||||||
|
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
if (!util.isObject(options))
|
||||||
|
options = {};
|
||||||
|
|
||||||
this.suicide = undefined;
|
this.suicide = undefined;
|
||||||
this.state = 'none';
|
this.state = options.state || 'none';
|
||||||
this.id = 0;
|
this.id = options.id | 0;
|
||||||
|
|
||||||
|
if (options.process) {
|
||||||
|
this.process = options.process;
|
||||||
|
this.process.on('error', this.emit.bind(this, 'error'));
|
||||||
|
this.process.on('message', this.emit.bind(this, 'message'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
util.inherits(Worker, EventEmitter);
|
util.inherits(Worker, EventEmitter);
|
||||||
|
|
||||||
@ -190,26 +202,6 @@ if (cluster.isMaster)
|
|||||||
else
|
else
|
||||||
workerInit();
|
workerInit();
|
||||||
|
|
||||||
|
|
||||||
function createWorkerExecArgv(masterExecArgv, worker) {
|
|
||||||
var args = masterExecArgv.slice();
|
|
||||||
var debugPort = process.debugPort + worker.id;
|
|
||||||
var hasDebugArg = false;
|
|
||||||
|
|
||||||
for (var i = 0; i < args.length; i++) {
|
|
||||||
var match = args[i].match(/^(--debug|--debug-brk)(=\d+)?$/);
|
|
||||||
if (!match) continue;
|
|
||||||
args[i] = match[1] + '=' + debugPort;
|
|
||||||
hasDebugArg = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasDebugArg)
|
|
||||||
args = ['--debug-port=' + debugPort].concat(args);
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function masterInit() {
|
function masterInit() {
|
||||||
cluster.workers = {};
|
cluster.workers = {};
|
||||||
|
|
||||||
@ -278,21 +270,46 @@ function masterInit() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var ids = 0;
|
function createWorkerProcess(id, env) {
|
||||||
cluster.fork = function(env) {
|
|
||||||
cluster.setupMaster();
|
|
||||||
var worker = new Worker;
|
|
||||||
worker.id = ++ids;
|
|
||||||
var workerEnv = util._extend({}, process.env);
|
var workerEnv = util._extend({}, process.env);
|
||||||
|
var execArgv = cluster.settings.execArgv.slice();
|
||||||
|
var debugPort = process.debugPort + id;
|
||||||
|
var hasDebugArg = false;
|
||||||
|
|
||||||
workerEnv = util._extend(workerEnv, env);
|
workerEnv = util._extend(workerEnv, env);
|
||||||
workerEnv.NODE_UNIQUE_ID = '' + worker.id;
|
workerEnv.NODE_UNIQUE_ID = '' + id;
|
||||||
worker.process = fork(cluster.settings.exec, cluster.settings.args, {
|
|
||||||
|
for (var i = 0; i < execArgv.length; i++) {
|
||||||
|
var match = execArgv[i].match(/^(--debug|--debug-brk)(=\d+)?$/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
execArgv[i] = match[1] + '=' + debugPort;
|
||||||
|
hasDebugArg = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasDebugArg)
|
||||||
|
execArgv = ['--debug-port=' + debugPort].concat(execArgv);
|
||||||
|
|
||||||
|
return fork(cluster.settings.exec, cluster.settings.args, {
|
||||||
env: workerEnv,
|
env: workerEnv,
|
||||||
silent: cluster.settings.silent,
|
silent: cluster.settings.silent,
|
||||||
execArgv: createWorkerExecArgv(cluster.settings.execArgv, worker),
|
execArgv: execArgv,
|
||||||
gid: cluster.settings.gid,
|
gid: cluster.settings.gid,
|
||||||
uid: cluster.settings.uid
|
uid: cluster.settings.uid
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids = 0;
|
||||||
|
|
||||||
|
cluster.fork = function(env) {
|
||||||
|
cluster.setupMaster();
|
||||||
|
var id = ++ids;
|
||||||
|
var workerProcess = createWorkerProcess(id, env);
|
||||||
|
var worker = new Worker({
|
||||||
|
id: id,
|
||||||
|
process: workerProcess
|
||||||
|
});
|
||||||
worker.process.once('exit', function(exitCode, signalCode) {
|
worker.process.once('exit', function(exitCode, signalCode) {
|
||||||
worker.suicide = !!worker.suicide;
|
worker.suicide = !!worker.suicide;
|
||||||
worker.state = 'dead';
|
worker.state = 'dead';
|
||||||
@ -307,8 +324,6 @@ function masterInit() {
|
|||||||
cluster.emit('disconnect', worker);
|
cluster.emit('disconnect', worker);
|
||||||
delete cluster.workers[worker.id];
|
delete cluster.workers[worker.id];
|
||||||
});
|
});
|
||||||
worker.process.on('error', worker.emit.bind(worker, 'error'));
|
|
||||||
worker.process.on('message', worker.emit.bind(worker, 'message'));
|
|
||||||
worker.process.on('internalMessage', internal(worker, onmessage));
|
worker.process.on('internalMessage', internal(worker, onmessage));
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
cluster.emit('fork', worker);
|
cluster.emit('fork', worker);
|
||||||
@ -447,11 +462,12 @@ function workerInit() {
|
|||||||
|
|
||||||
// Called from src/node.js
|
// Called from src/node.js
|
||||||
cluster._setupWorker = function() {
|
cluster._setupWorker = function() {
|
||||||
var worker = new Worker;
|
var worker = new Worker({
|
||||||
|
id: +process.env.NODE_UNIQUE_ID | 0,
|
||||||
|
process: process,
|
||||||
|
state: 'online'
|
||||||
|
});
|
||||||
cluster.worker = worker;
|
cluster.worker = worker;
|
||||||
worker.id = +process.env.NODE_UNIQUE_ID | 0;
|
|
||||||
worker.state = 'online';
|
|
||||||
worker.process = process;
|
|
||||||
process.once('disconnect', function() {
|
process.once('disconnect', function() {
|
||||||
if (!worker.suicide) {
|
if (!worker.suicide) {
|
||||||
// Unexpected disconnect, master exited, or some such nastiness, so
|
// Unexpected disconnect, master exited, or some such nastiness, so
|
||||||
@ -459,8 +475,6 @@ function workerInit() {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
worker.process.on('error', worker.emit.bind(worker, 'error'));
|
|
||||||
worker.process.on('message', worker.emit.bind(worker, 'message'));
|
|
||||||
process.on('internalMessage', internal(worker, onmessage));
|
process.on('internalMessage', internal(worker, onmessage));
|
||||||
send({ act: 'online' });
|
send({ act: 'online' });
|
||||||
function onmessage(message, handle) {
|
function onmessage(message, handle) {
|
||||||
|
49
test/simple/test-cluster-worker-constructor.js
Normal file
49
test/simple/test-cluster-worker-constructor.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright Joyent, Inc. and other Node contributors.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
// persons to whom the Software is furnished to do so, subject to the
|
||||||
|
// following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||||
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
// test-cluster-worker-constructor.js
|
||||||
|
// validates correct behavior of the cluster.Worker constructor
|
||||||
|
|
||||||
|
var common = require('../common');
|
||||||
|
var assert = require('assert');
|
||||||
|
var cluster = require('cluster');
|
||||||
|
var worker;
|
||||||
|
|
||||||
|
worker = new cluster.Worker();
|
||||||
|
assert.equal(worker.suicide, undefined);
|
||||||
|
assert.equal(worker.state, 'none');
|
||||||
|
assert.equal(worker.id, 0);
|
||||||
|
assert.equal(worker.process, undefined);
|
||||||
|
|
||||||
|
worker = new cluster.Worker({
|
||||||
|
id: 3,
|
||||||
|
state: 'online',
|
||||||
|
process: process
|
||||||
|
});
|
||||||
|
assert.equal(worker.suicide, undefined);
|
||||||
|
assert.equal(worker.state, 'online');
|
||||||
|
assert.equal(worker.id, 3);
|
||||||
|
assert.equal(worker.process, process);
|
||||||
|
|
||||||
|
worker = cluster.Worker.call({}, {id: 5});
|
||||||
|
assert(worker instanceof cluster.Worker);
|
||||||
|
assert.equal(worker.id, 5);
|
Loading…
x
Reference in New Issue
Block a user