UNPKG

@ovotech/genesys-web-messaging-tester

Version:
119 lines (118 loc) 5.25 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReorderedMessageDelayer = void 0; const events_1 = require("events"); const debug_1 = __importDefault(require("debug")); const timers_1 = require("timers"); const orderByTimestamp_1 = require("./orderByTimestamp"); const WebMessengerGuestSession_1 = require("../WebMessengerGuestSession"); /** * Reorders messages with a timestamp, being sure to maintain the overall order of messages with/without * timestamps. * * > All messaging follows a request/response pattern. However, web messaging is an asynchronous * > channel and therefore no guarantee to ordering is provided. * > Source: https://developer.genesys.cloud/commdigital/digital/webmessaging/websocketapi#messaging */ class ReorderedMessageDelayer extends events_1.EventEmitter { constructor(delayBeforeEmittingInMs = 1000, intervalInMs = 1000, intervalSet = timers_1.setInterval, intervalClear = clearInterval) { super(); this.delayBeforeEmittingInMs = delayBeforeEmittingInMs; this.intervalInMs = intervalInMs; this.intervalSet = intervalSet; this.intervalClear = intervalClear; this.messages = []; this.lastMessageWithTimestamp = undefined; this.unorderedMessageOccurred = false; if (intervalInMs <= 0) { throw new Error('Interval must be greater than 0'); } } logUnorderedMessageTimeDiff(message) { if ((0, WebMessengerGuestSession_1.isStructuredMessage)(message)) { if (this.lastMessageWithTimestamp) { const timeDifference = new Date(message.body.channel.time).getTime() - new Date(this.lastMessageWithTimestamp.body.channel.time).getTime(); if (timeDifference < 0) { this.unorderedMessageOccurred = true; ReorderedMessageDelayer.debugger("Message received was out of order. Last msg's timestamp came before this one by %d ms", -timeDifference); } else { // If timeDifference check above is true then last message is more recent so keep, else update below this.lastMessageWithTimestamp = message; } } else { this.lastMessageWithTimestamp = message; } } } get unorderdMessageDetected() { return this.unorderedMessageOccurred; } /** * Add a message to the pool. Each message added reset a timer to wait for any other messages * before releasing the oldest message. */ add(message, received) { this.logUnorderedMessageTimeDiff(message); this.messages.push({ received, response: message }); if (!this.intervalReference) { this.startInterval(); } } startInterval() { if (!this.intervalReference) { this.intervalReference = this.intervalSet(() => this.emitMessagesAfterSilence(), this.intervalInMs); ReorderedMessageDelayer.debugger('Interval started'); } } stopInterval() { if (this.intervalReference) { this.intervalClear(this.intervalReference); this.intervalReference = undefined; ReorderedMessageDelayer.debugger('Interval stopped'); } } emitMessagesAfterSilence() { var _a, _b; const result = (0, orderByTimestamp_1.orderByTimestamp)(this.messages); if (result.wasRearranged) { ReorderedMessageDelayer.debugger('Flushing messages. Out of order message detected: %O', this.messages); } else { ReorderedMessageDelayer.debugger('Flushing messages. No out of order messages'); } this.messages = result.responses; if ((0, WebMessengerGuestSession_1.isStructuredMessage)(this.messages[0].response)) { const now = new Date().getTime(); const ageOfMessageInMs = now - this.messages[0].received.getTime(); if (ageOfMessageInMs >= this.delayBeforeEmittingInMs) { const message = (_a = this.messages.shift()) === null || _a === void 0 ? void 0 : _a.response; this.emit('message', message); ReorderedMessageDelayer.debugger('Emitted message with timestamp: %O', { msDelayed: ageOfMessageInMs, message, }); } } else { const message = (_b = this.messages.shift()) === null || _b === void 0 ? void 0 : _b.response; // No timestamp so just emit this.emit('message', message); ReorderedMessageDelayer.debugger('Emitted message without timestamp %O', message); } if (this.messages.length === 0) { this.stopInterval(); return; } } get delay() { return this.delayBeforeEmittingInMs; } } exports.ReorderedMessageDelayer = ReorderedMessageDelayer; ReorderedMessageDelayer.debugger = (0, debug_1.default)('ReorderedMessageDelayer');