168 lines
No EOL
4.2 KiB
JavaScript
Executable file
168 lines
No EOL
4.2 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
|
|
|
const errorUtils = require('./errorUtils');
|
|
|
|
class Child {
|
|
constructor() {
|
|
this.module = undefined;
|
|
this.childId = undefined;
|
|
|
|
this.callQueue = [];
|
|
this.responseQueue = new Map();
|
|
this.responseId = 0;
|
|
this.maxConcurrentCalls = 10;
|
|
}
|
|
|
|
messageListener(data) {
|
|
if (data === 'die') {
|
|
return this.end();
|
|
}
|
|
|
|
if (data.type === 'module' && data.module && !this.module) {
|
|
this.module = require(data.module);
|
|
this.childId = data.child;
|
|
if (this.module.setChildReference) {
|
|
this.module.setChildReference(this);
|
|
}
|
|
return;
|
|
}
|
|
|
|
let type = data.type;
|
|
if (type === 'response') {
|
|
return this.handleResponse(data);
|
|
} else if (type === 'request') {
|
|
return this.handleRequest(data);
|
|
}
|
|
}
|
|
|
|
send(data) {
|
|
var _this = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
process.send(data, function (err) {
|
|
if (err && err instanceof Error) {
|
|
if (err.code === 'ERR_IPC_CHANNEL_CLOSED') {
|
|
// IPC connection closed
|
|
// no need to keep the worker running if it can't send or receive data
|
|
return _this.end();
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
}
|
|
|
|
handleRequest(data) {
|
|
var _this2 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
let idx = data.idx;
|
|
let child = data.child;
|
|
let method = data.method;
|
|
let args = data.args;
|
|
|
|
let result = { idx, child, type: 'response' };
|
|
try {
|
|
result.contentType = 'data';
|
|
result.content = yield _this2.module[method](...args);
|
|
} catch (e) {
|
|
result.contentType = 'error';
|
|
result.content = errorUtils.errorToJson(e);
|
|
}
|
|
|
|
_this2.send(result);
|
|
})();
|
|
}
|
|
|
|
handleResponse(data) {
|
|
var _this3 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
let idx = data.idx;
|
|
let contentType = data.contentType;
|
|
let content = data.content;
|
|
let call = _this3.responseQueue.get(idx);
|
|
|
|
if (contentType === 'error') {
|
|
call.reject(errorUtils.jsonToError(content));
|
|
} else {
|
|
call.resolve(content);
|
|
}
|
|
|
|
_this3.responseQueue.delete(idx);
|
|
|
|
// Process the next call
|
|
_this3.processQueue();
|
|
})();
|
|
}
|
|
|
|
// Keep in mind to make sure responses to these calls are JSON.Stringify safe
|
|
addCall(request, awaitResponse = true) {
|
|
var _this4 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
let call = request;
|
|
call.type = 'request';
|
|
call.child = _this4.childId;
|
|
call.awaitResponse = awaitResponse;
|
|
|
|
let promise;
|
|
if (awaitResponse) {
|
|
promise = new Promise(function (resolve, reject) {
|
|
call.resolve = resolve;
|
|
call.reject = reject;
|
|
});
|
|
}
|
|
|
|
_this4.callQueue.push(call);
|
|
_this4.processQueue();
|
|
|
|
return promise;
|
|
})();
|
|
}
|
|
|
|
sendRequest(call) {
|
|
var _this5 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
let idx;
|
|
if (call.awaitResponse) {
|
|
idx = _this5.responseId++;
|
|
_this5.responseQueue.set(idx, call);
|
|
}
|
|
_this5.send({
|
|
idx: idx,
|
|
child: call.child,
|
|
type: call.type,
|
|
location: call.location,
|
|
method: call.method,
|
|
args: call.args,
|
|
awaitResponse: call.awaitResponse
|
|
});
|
|
})();
|
|
}
|
|
|
|
processQueue() {
|
|
var _this6 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
if (!_this6.callQueue.length) {
|
|
return;
|
|
}
|
|
|
|
if (_this6.responseQueue.size < _this6.maxConcurrentCalls) {
|
|
_this6.sendRequest(_this6.callQueue.shift());
|
|
}
|
|
})();
|
|
}
|
|
|
|
end() {
|
|
return process.exit(0);
|
|
}
|
|
}
|
|
|
|
let child = new Child();
|
|
process.on('message', child.messageListener.bind(child));
|
|
|
|
module.exports = child; |