thread-pool
Version:
Simple thread pooling for Node.js.
181 lines (164 loc) • 4.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* Generate a string to be used as the body of each child process.
*/
function genProcessBody() {
/**
* This function will be invoked immediately upon evaluating the child
* process.
*/
var body = function body() {
/*
* The cache holds task files that have already been read in once.
* The handler will be the message handler for incoming message replies.
*/
var __cache = {};
var __messageHandlers = {};
var __counter = -1;
/**
* Handles `require` based on whether any ES6 transpiling has
* already occurred on a file.
*
* @param {String} path The path to the file.
*
* @return {Any} The required code.
*/
function req(path) {
if (__cache[path]) {
return __cache[path];
} else {
var required = require(path);
var captured = required.default ? required.default : required;
__cache[path] = captured;
return captured;
}
}
/**
* If we get a function task from the main thread, make sure it's
* actually callable.
*
* @param {String} text A stringified function.
*
* @return {String} A sanitized string.
*/
function sanitizeFn(text) {
return text.trim().replace(/^function\s*\(/, 'function __(');
}
/**
* Gernates an identifier for messages sent.
*
* @return {String}
*/
function genId() {
if (__counter > 9999999999) {
__counter = -1;
}
return +new Date() + ':' + __counter;
}
/**
* @class
*
* Provide the user with all the necessary tools.
*
* @param {Any} init The initial data coming in upon assignment.
*
* @return {undefined}
*/
function Handler(init) {
this.init = init;
}
/*
* Define the prototype for the Handler class.
*/
Handler.prototype = {
/**
* Allow the user to complete a task and put this child process
* back into the pool.
*
* @param {Any} output Serializable data to send back to the main thread.
*
* @return {undefined}
*/
finish: function finish(output) {
process.send({
type: 'done',
data: output
});
__messageHandlers = {};
},
/**
* Kills this thread.
*
* @return {undefined}
*/
err: function err() {
process.exit(1);
},
/**
* Let the user send data to the main thread.
*
* @param {Any} data Data to be sent.
*
* @type {Object} Contains a method called `onReply` that lets
* the user handle a reply to this message.
*/
send: function send(data) {
var id = genId();
process.send({ type: 'message', data: data, id: id });
return { onReply: function onReply(fn) {
return __messageHandlers[id] = fn;
} };
}
};
/**
* Executes a task passed in via a process message.
*
* @param {Object} msg Contains all message data.
*
* @return {undefined{}
*/
function execTask(msg) {
var task = void 0;
msg.isFunction ? eval('task = ' + sanitizeFn(msg.data.task)) : task = req(msg.data.task);
task.call(this, new Handler(JSON.parse(msg.data.init)));
}
/**
* If the user has set up a reply handler, call it when
* a reply comes in.
*
* @param {Object} msg The message that came in.
*
* @return {undefined}
*/
function handleReply(msg) {
if (__messageHandlers[msg.id]) {
__messageHandlers[msg.id](msg.data);
delete __messageHandlers[msg.id];
}
}
/*
* Handles incoming messages from the main thread.
*/
process.on('message', function (msg) {
switch (msg.type) {
case 'task':
return execTask(msg);
case 'reply':
return handleReply(msg);
default:
return;
}
});
};
/*
* Make sure we're producing a string.
*/
return '(' + body.toString() + '());';
}
/*
* Export the generated string.
*/
exports.default = genProcessBody();