UNPKG

cluster-service

Version:

Turns your single process code into a fault-resilient multi-process service with built-in REST & CLI support

115 lines (93 loc) 2.5 kB
var cservice = require("../cluster-service"); var util = require("util"); var cluster = require("cluster"); var async = require("async"); module.exports = { createMessage: createMessage, sendMessage: sendMessage, isValidMessage: isValidMessage, respondToMessage: respondToMessage, processMessage: processMessage }; var waiters = {}; var waiterId = 0; function isValidMessage(msg) { if (!msg || !msg.cservice || !msg.cservice.cmd) { return false; // ignore invalid cluster-service messages } return true; } function createMessage(cmd, options) { var msg = { cservice: util._extend({}, options || {}) }; msg.cservice.cmd = cmd; return msg; } function sendMessage(cmd, options, filter, cb) { var msg = createMessage(cmd, options); if (cluster.isWorker === true) { createWaiter(msg, process, cb); // send to master and wait for response return cservice.processSafeSend(process, msg); } var workers = cluster.workers; if (typeof filter === "function") { // filter as directed workers = workers.filter(filter); } var tasks = []; workers.forEach(function(worker) { tasks.push(createWaiterTask(msg, worker.process, cb)); }); // process worker messages, but callback only once async.parallel(tasks, function (err, data) { if (typeof cb === "function") { cb(err, data); } }); } function createWaiter(msg, process, cb) { if (typeof cb !== "function") { return; } msg.waiterId = "id" + (++waiterId); var waiter = waiters[msg.waiterId] = { msg: msg, process: process, cb: cb }; var cleanupCheck = setTimeout(function cleanup() { if (waiters[msg.waiterId]) { delete waiters[msg.waiterId]; cb(new Error('Timed out waiting in message bus')); } }, 5000); // If process exits, no need to clean up anymore cleanupCheck.unref(); return waiter; } function createWaiterTask(msg, process) { return function(asyncCb) { var waiter = createWaiter(msg, process, asyncCb); cservice.processSafeSend(process, msg); if (!waiter) { // if no waiter, cb immediately asyncCb(); } }; } function respondToMessage(msg, process, error, response) { msg.error = error; msg.response = response; cservice.processSafeSend(process, msg); } function processMessage(msg) { var waiter = waiters[msg.waiterId]; if (!waiter) { return false; } delete waiters[msg.waiterId]; waiter.cb(msg.error, msg.response); return true; }