'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 RPCManager { constructor(options) { this.callQueue = []; this.callId = 0; this.calls = new Map(); this.maxConcurrentCalls = options.maxConcurrentCalls || Infinity; this.send = options.send; } // Keep in mind to make sure responses to these calls are JSON.Stringify safe addCall(request, awaitResponse = true) { var _this = this; return _asyncToGenerator(function* () { // console.log('add call', request) let call = request; call.type = 'request'; call.child = _this.childId; call.awaitResponse = awaitResponse; let promise; if (awaitResponse) { promise = new Promise(function (resolve, reject) { call.resolve = resolve; call.reject = reject; }); } _this.callQueue.push(call); _this.processQueue(); return promise; })(); } sendRequest(call) { var _this2 = this; return _asyncToGenerator(function* () { let idx; if (call.awaitResponse) { idx = _this2.callId++; _this2.calls.set(idx, call); } return _this2.send({ idx: idx, child: call.child, type: call.type, location: call.location, method: call.method, args: call.args, awaitResponse: call.awaitResponse }); })(); } processQueue() { var _this3 = this; return _asyncToGenerator(function* () { if (!_this3.callQueue.length) { return; } if (_this3.calls.size < _this3.maxConcurrentCalls) { let call = _this3.callQueue[0]; if (_this3.sendRequest(call) !== false) { _this3.callQueue.shift(); } } })(); } handleMessage(data, child) { var _this4 = this; return _asyncToGenerator(function* () { // console.log('message', data) if (data.type === 'module' && data.module && !_this4.module) { _this4.module = require(data.module); _this4.childId = data.child; if (_this4.module.setChildReference) { _this4.module.setChildReference(_this4); } return; } if (data.type === 'response') { return _this4.handleResponse(data); } else if (data.type === 'request') { return _this4.handleRequest(data, child); } })(); } handleRequest(data, child) { var _this5 = this; return _asyncToGenerator(function* () { let result = { type: 'response', idx: data.idx, child: data.child }; let module = _this5.module; if (data.location) { module = require(data.location); } if (!module) { throw new Error('No module was specified'); } let func = data.method ? module[data.method] : module; if (typeof func !== 'function') { throw new Error('Module or method is not a function'); } try { result.contentType = 'data'; result.content = yield func(...data.args); } catch (e) { result.contentType = 'error'; result.content = errorUtils.errorToJson(e); } if (data.awaitResponse) { if (child) { child.send(result); } else { _this5.send(result); } } })(); } handleResponse(data, child) { var _this6 = this; return _asyncToGenerator(function* () { let idx = data.idx; let contentType = data.contentType; let content = data.content; let call = _this6.calls.get(idx); if (!call) { throw new Error(`Worker Farm: Received message for unknown call index. This should not happen!`); } if (contentType === 'error') { call.reject(errorUtils.jsonToError(content)); } else { call.resolve(content); } _this6.calls.delete(idx); if (child && child.calls) { child.calls.delete(idx); } // Process the next call _this6.processQueue(); })(); } } module.exports = RPCManager;