UNPKG

@bbc/sofie-server-core-integration

Version:
135 lines 5.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConnectionMethodsQueue = exports.TIMEOUTREPLY = exports.TIMEOUTCALL = void 0; exports.makeMethods = makeMethods; exports.makeMethodsLowPrio = makeMethodsLowPrio; const tslib_1 = require("tslib"); const underscore_1 = tslib_1.__importDefault(require("underscore")); function makeMethods(connection, methods) { const o = {}; underscore_1.default.each(methods, (value, methodName) => { o[methodName] = async (...args) => connection.callMethodRaw(value, args); }); return o; } function makeMethodsLowPrio(connection, methods) { const o = {}; underscore_1.default.each(methods, (value, methodName) => { o[methodName] = async (...args) => connection.callMethodLowPrioRaw(value, args); }); return o; } // low-prio calls: exports.TIMEOUTCALL = 200; // ms, time to wait after a call exports.TIMEOUTREPLY = 50; // ms, time to wait after a reply class ConnectionMethodsQueue { _triggerDoQueueTimer = null; _timeLastMethodCall = 0; _timeLastMethodReply = 0; queuedMethodCalls = []; _ddp; _credentials; constructor(ddp, credentials) { this._ddp = ddp; this._credentials = credentials; } /** * This should not be used directly, use the `coreMethods` wrapper instead. * Call a meteor method * @param methodName The name of the method to call * @param attrs Parameters to the method * @returns Resopnse, if any */ async callMethodRaw(methodName, attrs) { return new Promise((resolve, reject) => { if (!methodName) { reject(new Error('callMethod: argument missing: methodName')); return; } const fullAttrs = [this._credentials.deviceId, this._credentials.deviceToken].concat(attrs || []); this._timeLastMethodCall = Date.now(); if (!this._ddp.ddpClient) { reject(new Error('callMehod: DDP client has not been initialized')); return; } const timeout = setTimeout(() => { // Timeout console.error(`Timeout "${methodName}"`); console.error(JSON.stringify(fullAttrs)); reject(new Error(`Timeout when calling method "${methodName}", arguments: ${JSON.stringify(fullAttrs).slice(0, 200)}`)); }, 10 * 1000); // 10 seconds this._ddp.ddpClient.call(methodName, fullAttrs, (err, result) => { clearTimeout(timeout); this._timeLastMethodReply = Date.now(); if (err) { if (typeof err === 'object') { // Add a custom toString() method, because the default object will just print "[object Object]" err.toString = () => { if (err.message) { return err.message; // + (err.stack ? '\n' + err.stack : '') } else { return JSON.stringify(err); } }; } // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors reject(err); } else { resolve(result); } }); }); } async callMethodLowPrioRaw(methodName, attrs) { return new Promise((resolve, reject) => { this.queuedMethodCalls.push({ f: async () => { return this.callMethodRaw(methodName, attrs); }, resolve: resolve, reject: reject, }); this._triggerDoQueue(); }); } _triggerDoQueue(time = 2) { if (!this._triggerDoQueueTimer) { this._triggerDoQueueTimer = setTimeout(() => { this._triggerDoQueueTimer = null; this._doQueue(); }, time); } } _doQueue() { // check if we can send a call? const timeSinceLastMethodCall = Date.now() - this._timeLastMethodCall; const timeSinceLastMethodReply = Date.now() - this._timeLastMethodReply; if (timeSinceLastMethodCall < exports.TIMEOUTCALL) { // Not enough time has passed since last method call this._triggerDoQueue(exports.TIMEOUTCALL - timeSinceLastMethodCall + 1); } else if (timeSinceLastMethodReply < exports.TIMEOUTREPLY) { // Not enough time has passed since last method reply this._triggerDoQueue(exports.TIMEOUTREPLY - timeSinceLastMethodReply + 1); } else { // yep, it's time to send a command! const c = this.queuedMethodCalls.shift(); if (c) { c.f() .then((result) => { this._triggerDoQueue(); c.resolve(result); }) .catch((err) => { this._triggerDoQueue(); c.reject(err); }); } } } } exports.ConnectionMethodsQueue = ConnectionMethodsQueue; //# sourceMappingURL=methods.js.map