@ovotech/genesys-web-messaging-tester
Version:
119 lines (118 loc) • 5.25 kB
JavaScript
"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');