You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
2.9 KiB
110 lines
2.9 KiB
'use strict';
|
|
|
|
function getInstanceMethods(inst) {
|
|
var instanceMethods = Object.keys(inst)
|
|
.map(function (key) { return 'function' === typeof inst[key] ? key : null; })
|
|
.filter(function (key) { return key; })
|
|
;
|
|
|
|
var protoMethods = Object.keys(Object.getPrototypeOf(inst))
|
|
.map(function (key) { return 'function' === typeof Object.getPrototypeOf(inst)[key] ? key : null; })
|
|
.filter(function (key) { return key; })
|
|
;
|
|
|
|
return instanceMethods.concat(protoMethods);
|
|
}
|
|
|
|
function getMethods(inst, keys) {
|
|
if (!keys) {
|
|
keys = getInstanceMethods(inst);
|
|
}
|
|
|
|
return keys.filter(function (key) {
|
|
if ('function' === typeof inst[key]) {
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
function setup(opts) {
|
|
var crypto = require('crypto');
|
|
var methods = getMethods(opts.instance, opts.methods);
|
|
var token = crypto.randomBytes(16).toString('hex');
|
|
var inst = opts.instance;
|
|
var prefixes = require('./prefixes.js').create(opts); // uses opts.name
|
|
|
|
opts.master = opts.master || require('./process/master').create(prefixes);
|
|
|
|
opts.master.on('connection', function (w) {
|
|
if (opts.debug) { console.log('[cluster-rpc] [master] worker connected'); }
|
|
w.send({
|
|
methods: methods
|
|
, _token: token
|
|
, type: prefixes.init
|
|
});
|
|
|
|
w.on('message', function (cmd) {
|
|
if (0 !== (cmd.type||'').indexOf(prefixes.root)) {
|
|
//console.log('debug w: got unknown message type');
|
|
return;
|
|
}
|
|
|
|
if (token !== cmd._token) {
|
|
//console.log('debug w: got bad token');
|
|
return;
|
|
}
|
|
|
|
if (!Array.isArray(cmd.args)) {
|
|
throw new Error("[Sanity Fail] 'args' should be array of arguments");
|
|
}
|
|
|
|
switch (cmd.type) {
|
|
case prefixes.rpc:
|
|
cmd.args.push(function callback() {
|
|
// args is probably err, data in most cases
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
w.send({
|
|
args: args
|
|
, id: cmd.id
|
|
//, this: this
|
|
, _token: token
|
|
, type: prefixes.result
|
|
});
|
|
});
|
|
|
|
inst[cmd.func].apply(inst, cmd.args);
|
|
break;
|
|
|
|
default:
|
|
throw new Error("cluster-ipc UNKNOWN TYPE");
|
|
//break;
|
|
}
|
|
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports.create = function (opts) {
|
|
if (opts.debug) { console.log('[cluster-rpc] [master] create'); }
|
|
var cluster = require('cluster');
|
|
var PromiseA = opts.PromiseA || global.Promise || require('bluebird');
|
|
var init = false;
|
|
|
|
opts._promise = PromiseA.resolve(opts.instance);
|
|
opts._promise.addWorker = function (w) {
|
|
if (opts.debug) { console.log('[cluster-rpc] [master] addWorker wrapper'); }
|
|
if (!init) {
|
|
init = true;
|
|
setup(opts);
|
|
}
|
|
return opts.master.addWorker(w);
|
|
};
|
|
|
|
if (false !== opts.addOnFork) {
|
|
if (opts.debug) { console.log('[cluster-rpc] [master] -- will call addWorker on each fork'); }
|
|
cluster.on('fork', opts._promise.addWorker);
|
|
}
|
|
|
|
return opts._promise;
|
|
};
|
|
|