@bbc/sofie-server-core-integration
Version:
Library for connecting to Core
135 lines • 5.36 kB
JavaScript
;
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