UNPKG

@microsoft/omnichannel-chat-sdk

Version:
274 lines (273 loc) 12.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * AWTTransmissionManagerCore.ts * @author Abhilash Panwar (abpanwar) * @copyright Microsoft 2017 */ var DataModels_1 = require("./DataModels"); var Enums_1 = require("../common/Enums"); var AWTQueueManager_1 = require("./AWTQueueManager"); var AWTStatsManager_1 = require("../common/AWTStatsManager"); var AWTEventProperties_1 = require("./AWTEventProperties"); var AWTLogManager_1 = require("./AWTLogManager"); var Utils = require("../common/Utils"); var MaxBackoffCount = 4; var MinDurationBetweenUploadNow = 30000; //30 sec var StatName = 'awt_stats'; /** * Class that manages the timers for when to send events. It also * handles flush and flushAndTeardown. This class also allows setting * new event handlers. The default event handler is the Inbound Queue Manager. */ var AWTTransmissionManagerCore = /** @class */ (function () { function AWTTransmissionManagerCore() { } /** * Sets the event handler to be used by the tranmission manager. * The default event handler is the Inbound queue manager. This handler * is used to batch and send events to Aria. If you intend to send events * to Aria please make sure your event handler forwards events to the Inbound * Queue Manager. You can retrieve the Inbound Queue Manager by calling * getEventsHandler before you set your handler. * @param {object} eventsHandler - The new events handler to be used by the tranmission * manager. */ AWTTransmissionManagerCore.setEventsHandler = function (eventsHandler) { this._eventHandler = eventsHandler; }; /** * Gets the current event handler used by the tranmission manager. * @return {object} The event handler currently used by the tranmission manager. */ AWTTransmissionManagerCore.getEventsHandler = function () { return this._eventHandler; }; /** * Try to schedule the timer after which events will be sent. If there are * no events to be sent, or there is already a timer scheduled, or the * http manager doesn't have any idle connections this method is no-op. */ AWTTransmissionManagerCore.scheduleTimer = function () { var _this = this; var timer = this._profiles[this._currentProfile][2]; if (this._timeout < 0 && timer >= 0 && !this._paused) { if (this._eventHandler.hasEvents()) { //If the transmission is backed off make the timer atleast 1 sec to allow for backoff. if (timer === 0 && this._currentBackoffCount > 0) { timer = 1; } this._timeout = setTimeout(function () { return _this._batchAndSendEvents(); }, timer * (1 << this._currentBackoffCount) * 1000); } else { this._timerCount = 0; } } }; /** * Initialize the transmission manager. After this method is called events are * accepted for tranmission. * @param {object} config - The configuration passed during AWTLogManager initialize. */ AWTTransmissionManagerCore.initialize = function (config) { var _this = this; this._newEventsAllowed = true; this._config = config; this._eventHandler = new AWTQueueManager_1.default(config.collectorUri, config.cacheMemorySizeLimitInNumberOfEvents, config.httpXHROverride, config.clockSkewRefreshDurationInMins); this._initializeProfiles(); AWTStatsManager_1.default.initialize(function (stats, tenantId) { if (_this._config.canSendStatEvent(StatName)) { var event_1 = new AWTEventProperties_1.default(StatName); event_1.setEventPriority(Enums_1.AWTEventPriority.High); event_1.setProperty('TenantId', tenantId); for (var statKey in stats) { if (stats.hasOwnProperty(statKey)) { event_1.setProperty(statKey, stats[statKey].toString()); } } AWTLogManager_1.default.getLogger(Utils.StatsApiKey).logEvent(event_1); } }); }; /** * Set the transmit profile to be used. This will change the tranmission timers * based on the transmit profile. * @param {string} profileName - The name of the transmit profile to be used. */ AWTTransmissionManagerCore.setTransmitProfile = function (profileName) { if (this._currentProfile !== profileName && this._profiles[profileName] !== undefined) { this.clearTimeout(); this._currentProfile = profileName; this.scheduleTimer(); } }; /** * Load custom tranmission profiles. Each profile should have timers for * high, normal and low. Each profile should make sure * that a each priority timer is a multiple of the priority higher than it. * Setting the timer value to -1 means that the events for that priority will * not be sent. Note that once a priority has been set to not send, all priorities * below it will also not be sent. The timers should be in the form of [low, normal, high]. * e.g Custom: [30,10,5] * This also removes any previously loaded custom profiles. * @param {object} profiles - A dictionary containing the transmit profiles. */ AWTTransmissionManagerCore.loadTransmitProfiles = function (profiles) { this._resetTransmitProfiles(); for (var profileName in profiles) { if (profiles.hasOwnProperty(profileName)) { if (profiles[profileName].length !== 3) { continue; } //Make sure if a higher priority is set to not send then dont send lower priority for (var i = 2; i >= 0; --i) { if (profiles[profileName][i] < 0) { for (var j = i; j >= 0; --j) { profiles[profileName][j] = -1; } break; } } //Make sure each priority is multiple of the priority higher then it. If not a multiple //we round up so that it becomes a multiple. for (var i = 2; i > 0; --i) { if (profiles[profileName][i] > 0 && profiles[profileName][i - 1] > 0) { var timerMultiplier = profiles[profileName][i - 1] / profiles[profileName][i]; profiles[profileName][i - 1] = Math.ceil(timerMultiplier) * profiles[profileName][i]; } } this._profiles[profileName] = profiles[profileName]; } } }; /** * Pass the event to the event handler and try to schedule the timer. * @param {object} event - The event to be sent. */ AWTTransmissionManagerCore.sendEvent = function (event) { if (this._newEventsAllowed) { //If the transmission is backed off then do not send synchronous events. //We will convert these events to High priority instead. if (this._currentBackoffCount > 0 && event.priority === Enums_1.AWTEventPriority.Immediate_sync) { event.priority = Enums_1.AWTEventPriority.High; } this._eventHandler.addEvent(event); this.scheduleTimer(); } }; /** * Sends events for all priority for the current inbound queue. * This method adds new inbound queues to which new events will be added. * Note: If LogManager is paused or flush is called again in less than 30 sec * then flush will be no-op and the callback will not be called. * @param {function} callback - The function to be called when flush is finished. */ AWTTransmissionManagerCore.flush = function (callback) { var currentTime = (new Date()).getTime(); if (!this._paused && this._lastUploadNowCall + MinDurationBetweenUploadNow < currentTime) { this._lastUploadNowCall = currentTime; if (this._timeout > -1) { clearTimeout(this._timeout); this._timeout = -1; } this._eventHandler.uploadNow(callback); } }; /** * Pauses transmission. It pauses the http manager and also clears timers. */ AWTTransmissionManagerCore.pauseTransmission = function () { if (!this._paused) { this.clearTimeout(); this._eventHandler.pauseTransmission(); this._paused = true; } }; /** * Resumes tranmission. It resumes the http manager and tries to schedule the timer. */ AWTTransmissionManagerCore.resumeTransmision = function () { if (this._paused) { this._paused = false; this._eventHandler.resumeTransmission(); this.scheduleTimer(); } }; /** * Stops allowing new events being added for tranmission. It also batches all * events currently in the queue and creates requests from them to be sent. */ AWTTransmissionManagerCore.flushAndTeardown = function () { AWTStatsManager_1.default.teardown(); this._newEventsAllowed = false; this.clearTimeout(); //No op if offline storage is added this._eventHandler.teardown(); }; /** * Backs off tranmission. This exponentially increases all the timers. */ AWTTransmissionManagerCore.backOffTransmission = function () { if (this._currentBackoffCount < MaxBackoffCount) { this._currentBackoffCount++; this.clearTimeout(); this.scheduleTimer(); } }; /** * Clears backoff for tranmission. */ AWTTransmissionManagerCore.clearBackOff = function () { if (this._currentBackoffCount > 0) { this._currentBackoffCount = 0; this.clearTimeout(); this.scheduleTimer(); } }; /** * Resets the transmit profiles to the default profiles of Real Time, Near Real Time * and Best Effort. This removes all the custom profiles that were loaded. */ AWTTransmissionManagerCore._resetTransmitProfiles = function () { this.clearTimeout(); this._initializeProfiles(); this._currentProfile = DataModels_1.AWT_REAL_TIME; this.scheduleTimer(); }; AWTTransmissionManagerCore.clearTimeout = function () { if (this._timeout > 0) { clearTimeout(this._timeout); this._timeout = -1; this._timerCount = 0; } }; AWTTransmissionManagerCore._batchAndSendEvents = function () { var priority = Enums_1.AWTEventPriority.High; this._timerCount++; if (this._timerCount * this._profiles[this._currentProfile][2] === this._profiles[this._currentProfile][0]) { priority = Enums_1.AWTEventPriority.Low; this._timerCount = 0; } else if (this._timerCount * this._profiles[this._currentProfile][2] === this._profiles[this._currentProfile][1]) { priority = Enums_1.AWTEventPriority.Normal; } this._eventHandler.sendEventsForPriorityAndAbove(priority); this._timeout = -1; this.scheduleTimer(); }; AWTTransmissionManagerCore._initializeProfiles = function () { this._profiles = {}; this._profiles[DataModels_1.AWT_REAL_TIME] = [4, 2, 1]; this._profiles[DataModels_1.AWT_NEAR_REAL_TIME] = [12, 6, 3]; this._profiles[DataModels_1.AWT_BEST_EFFORT] = [36, 18, 9]; }; AWTTransmissionManagerCore._newEventsAllowed = false; AWTTransmissionManagerCore._currentProfile = DataModels_1.AWT_REAL_TIME; AWTTransmissionManagerCore._timeout = -1; AWTTransmissionManagerCore._currentBackoffCount = 0; AWTTransmissionManagerCore._paused = false; AWTTransmissionManagerCore._timerCount = 0; AWTTransmissionManagerCore._lastUploadNowCall = 0; return AWTTransmissionManagerCore; }()); exports.default = AWTTransmissionManagerCore;