janode
Version:
Meetecho adapter for the Janus WebRTC Server
225 lines (190 loc) • 6.74 kB
JavaScript
'use strict';
/**
* This module contains the transaction manager used by janode.
* It is possible to debug the size of the transaction table (to detect leaks) by using the CLI argument `--debug-tx`.
* @module tmanager
* @private
*/
/**
* An object describing a pending transaction stored in the manager.
*
* @typedef {Object} PendingTransaction
* @property {string} id - The transaction identifier
* @property {Object} owner - A reference to the object that created the transaction
* @property {string} request - The janus request for the pending transaction
* @property {function} done - The success callback
* @property {function} error - The error callback
*/
import Logger from './utils/logger.js';
const LOG_NS = '[tmanager.js]';
import { getNumericID, getCliArgument } from './utils/utils.js';
const debug = getCliArgument('debug-tx', 'boolean', false);
/**
* Class representing a Janode Transaction Manager (TM).
* A transaction manager stores the pending transactions and has methods to create and close transactions.
* Every transaction objects has an identifier, a reference to the owner and a kind of janus request.
*
* @private
*/
class TransactionManager {
/**
* Create a Transacton Manager (TM)
*
* @param {string} [id] - The identifier given to the manager (got from a counter if missing)
*/
constructor(id = getNumericID()) {
this.transactions = new Map();
this.id = id;
Logger.info(`${LOG_NS} [${this.id}] creating new transaction manager (debug=${debug})`);
this._dbgtask = null;
/* If tx debugging is enabled, periodically print the size of the tx table */
}
/**
* Clear the internal transaction table and the debugging printing task.
*/
clear() {
Logger.info(`${LOG_NS} [${this.id}] clearing transaction manager`);
clearInterval(this._dbgtask);
this.transactions.clear();
}
/**
* Check if the TM has a specific transaction.
*
* @param {string} id - The transaction id
* @returns {boolean} True if the manager contains the transaction
*/
has(id) {
if (!id) return false;
return this.transactions.has(id);
}
/**
* Get a specific transaction from the TM.
*
* @param {string} id - The transaction id
* @returns {PendingTransaction|void} The wanted transaction, or nothing if missing
*/
get(id) {
if (!id) return null;
if (!this.has(id)) return null;
return this.transactions.get(id);
}
/**
* Get the current size of the transaction table.
*
* @returns {number} The size of the table
*/
size() {
return this.transactions.size;
}
/**
* Add a pending transaction to the TM.
*
* @param {string} id - The transaction id
* @param {PendingTransaction} transaction
*/
set(id, transaction) {
if (!id) return;
if (!transaction) return;
this.transactions.set(id, transaction);
if (debug && !this._dbgtask) {
this._dbgtask = setInterval(_ => {
Logger.info(`${LOG_NS} [${this.id}] TM DEBUG size=${this.size()}`);
}, 5000);
}
}
/**
* Delete a specific transaction from the TM.
*
* @param {string} id - The transaction id to delete
*/
delete(id) {
if (!id) return;
if (!this.has(id)) return;
this.transactions.delete(id);
}
/**
* Get the owner of a specific transaction id.
*
* @param {string} id - The transaction id
* @returns {object|void} A reference to the owner object, or nothing if transaction is missing
*/
getTransactionOwner(id) {
if (!id) return;
if (!this.has(id)) return;
return this.get(id).owner;
}
/**
* Create a new transaction if id does not exist in the table and add it to the TM.
*
* @param {string} id - The transaction identifier
* @param {Object} owner - A reference to the object that created the transaction
* @param {string} request - The janus request for the pending transaction
* @param {function} done - The success callback
* @param {function} error - The error callback
* @returns {PendingTransaction|void} The newly created transaction, or nothing if the id already exists
*/
createTransaction(id, owner, request, done, error) {
if (this.has(id)) return;
const tx = {
id,
owner,
request,
done,
error,
};
this.set(id, tx);
Logger.verbose(`${LOG_NS} [${tx.owner.id}] created new transaction ${id}, request "${tx.request}"`);
return tx;
}
/**
* Close a transaction with an error if the id is found and the owner matches.
* The closed transaction will be removed from the internal table and the error cb will be invoked with the error string.
*
* @param {string} id - The transaction identifier
* @param {Object} owner - A reference to the transaction owner
* @param {Error} error - The error object
* @returns {PendingTransaction|void} The closed transaction, or nothing if the id does not exist or the owner does not match
*/
closeTransactionWithError(id, owner, error) {
const tx = this.get(id);
if (!tx) return;
if (tx.owner !== owner) return;
this.delete(id);
tx.error(error);
Logger.verbose(`${LOG_NS} [${tx.owner.id}] closed with error transaction ${id}, request "${tx.request}"`);
return tx;
}
/**
* Close all the stored transactions with an error.
* If an owner is specified only the owner's transaction will be closed.
* The closed transactions will be removed from the internal table.
*
* @param {Object} [owner] - A reference to the transaction owner
* @param {Error} error - The error object
*/
closeAllTransactionsWithError(owner, error) {
for (const [_, pendingTx] of this.transactions) {
if (!owner || pendingTx.owner === owner)
this.closeTransactionWithError(pendingTx.id, pendingTx.owner, error);
}
}
/**
* Close a transaction with success if the id is found and the owner matches.
* The closed transaction will be removed from the internal table and the success cb will be invoked with the specified data.
*
* @param {string} id - The transaction identifier
* @param {Object} owner - A reference to the transaction owner
* @param {Object} data - The success callback data
* @returns {PendingTransaction|void} The closed transaction, or nothing if the id does not exist or the owner does not match
*/
closeTransactionWithSuccess(id, owner, data) {
const tx = this.get(id);
if (!tx) return;
if (tx.owner !== owner) return;
this.delete(id);
tx.done(data);
Logger.verbose(`${LOG_NS} [${tx.owner.id}] closed with success transaction ${id}, request "${tx.request}"`);
return tx;
}
}
export default TransactionManager;