UNPKG

@skylineos/clsp-player

Version:

Skyline Technology Solutions' CLSP Video Player. Stream video in near-real-time in modern browsers.

178 lines (145 loc) 3.93 kB
import RouterBaseManager from './RouterBaseManager'; const DEFAULT_PUBLISH_STATS_INTERVAL = 5; export default class RouterStatsManager extends RouterBaseManager { /** * @static * * The events that this RouterStatsManager will emit. */ static events = { PUBLISH_FAILURE: 'publish-failed', }; /** * @static * * The Router events that this Router Manager is responsible for */ static routerEvents = {}; static factory ( logId, clientId, routerTransactionManager, ) { return new RouterStatsManager( logId, clientId, routerTransactionManager, ); } constructor ( logId, clientId, routerTransactionManager, ) { super( logId, clientId, ); if (!routerTransactionManager) { throw new Error('A RouterTransactionManager is required to instantiate a RouterStatsManager'); } this.routerTransactionManager = routerTransactionManager; this.statsMsg = { byteCount: 0, inkbps: 0, host: document.location.host, clientId: this.clientId, }; this.publishInterval = null; this.isStopped = true; // configurable state this.PUBLISH_STATS_INTERVAL = DEFAULT_PUBLISH_STATS_INTERVAL; } /** * Update the stats byte count with the byteArray / segment. To be called * when the segment is appended to the MSE SourceBuffer. * * @param {*} byteArray */ updateByteCount (byteArray) { if (this.isDestroyed) { this.logger.info('Tried to updateByteCount while destroyed'); return; } this.logger.silly('Updating bytecount...'); this.statsMsg.byteCount += byteArray.length; } /** * We have to send stats to the server at least once per minute, or else the * CLSP service will stop streaming to this Router. * * @returns {void} */ start () { if (this.isDestroyed) { this.logger.info('Tried to start while destroyed'); return; } if (this.publishInterval) { this.stop(); } this.logger.info('Starting stats publishing...'); this.publishInterval = setInterval(() => { this._publishStats(); }, this.PUBLISH_STATS_INTERVAL * 1000); this.isStopped = false; } /** * Stop publishing stats to the server. Do this When we no longer want to * stream to the Router. * * @returns {void} */ stop () { if (this.isDestroyComplete) { this.logger.info('Tried to stop while destroyed'); return; } this.logger.info('Stopping stats publishing...'); if (this.publishInterval) { clearInterval(this.publishInterval); this.publishInterval = null; } this.isStopped = true; } /** * @private * * @async * * Send stats to the server. * * @returns {void} */ async _publishStats () { if (this.isDestroyed) { this.logger.info('Tried to _publishStats while destroyed'); return; } this.statsMsg.inkbps = (this.statsMsg.byteCount * 8) / 30000.0; this.statsMsg.byteCount = 0; try { this.logger.info('About to send stats message...'); await this.routerTransactionManager.publish('iov/stats', this.statsMsg); this.logger.debug('iov status', this.statsMsg); } catch (error) { // This prevents the errors from displaying when stopped, e.g. after the // iframe has been destroyed if (!this.isStopped) { this.logger.error('Error while publishing stats!'); this.logger.error(error); this.emit(RouterStatsManager.events.PUBLISH_FAILURE, { error }); // If any publish operation fails, do not continue to try to send stats // messages. It is up to the caller how to respond. this.stop(); } } } async _destroy () { this.stop(); this.statsMsg = null; this.routerTransactionManager = null; await super._destroy(); } }