UNPKG

vtex

Version:

The platform for e-commerce apps

166 lines (165 loc) 6.01 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const eventsource_1 = tslib_1.__importDefault(require("eventsource")); const env_1 = require("../../api/env"); const user_agent_1 = tslib_1.__importDefault(require("../../user-agent")); const Headers_1 = require("../constants/Headers"); const SessionManager_1 = require("../../api/session/SessionManager"); const EventSourceError_1 = require("./EventSourceError"); const traceConfig_1 = require("../globalConfigs/traceConfig"); // Colossus ping is set at 45s const COLOSSUS_PING = 45000; const EPSILON = 5000; const BEFORE_NEXT_PING = COLOSSUS_PING - EPSILON; const AFTER_NEXT_PING = COLOSSUS_PING + EPSILON; const CONNECTION_CLOSED = 2; const DEFAULT_RECONNECT_INTERVAL = 1000; const MAX_RETRIES = 3; class CustomEventSource { constructor(source, configuration) { var _a; this.restartCount = 0; this.errorCount = 0; this.pingEventsCount = 0; this.source = source; this.configuration = configuration; this.events = []; this.eventSource = null; this.isClosed = false; this.nRetries = 0; this.pingStatus = {}; this.checkPing = this.checkPing.bind(this); this.handleError = this.handleError.bind(this); this.reconnect = this.reconnect.bind(this); this.connectEventSource(); this.addColossusPing(); this.reconnectInterval = ((_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.reconnectInterval) || DEFAULT_RECONNECT_INTERVAL; } static create(opts) { const { source, closeOnInvalidToken = false, additionalHeaders = {} } = opts; const traceHeader = traceConfig_1.TraceConfig.shouldTrace() ? { [Headers_1.Headers.VTEX_TRACE]: traceConfig_1.TraceConfig.jaegerDebugID } : null; let token; if (closeOnInvalidToken) { token = SessionManager_1.SessionManager.getSingleton().checkAndGetToken(closeOnInvalidToken); } else { token = SessionManager_1.SessionManager.getSingleton().token; } return new CustomEventSource(source, { headers: { authorization: `bearer ${token}`, 'user-agent': user_agent_1.default, ...(env_1.envCookies() ? { cookie: env_1.envCookies() } : null), ...(env_1.cluster() ? { [Headers_1.Headers.VTEX_UPSTREAM_TARGET]: env_1.cluster() } : null), ...additionalHeaders, ...traceHeader, }, }); } set onopen(newOnOpen) { this.esOnOpen = newOnOpen; this.esOnOpen = this.esOnOpen.bind(this); if (this.eventSource) { this.eventSource.onopen = this.esOnOpen; } } set onmessage(newOnMessage) { this.esOnMessage = newOnMessage; this.esOnMessage = this.esOnMessage.bind(this); if (this.eventSource) { this.eventSource.onmessage = this.esOnMessage; } } set onerror(newOnError) { this.esOnError = newOnError; this.esOnError = this.esOnError.bind(this); if (this.eventSource) { this.eventSource.onerror = this.handleError; } } addEventListener(event, handler) { this.events.push({ event, handler }); if (this.eventSource) { this.eventSource.addEventListener(event, handler); } } close() { this.closeEventSource(); this.clearTimers(); this.isClosed = true; } handleError(err) { var _a; this.errorCount += 1; if (typeof this.esOnError === 'function') { this.esOnError(this.createError(err)); } this.nRetries += 1; if (this.nRetries > MAX_RETRIES) { this.close(); } if (!this.eventSource || ((_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.readyState) === CONNECTION_CLOSED) { setTimeout(this.reconnect, this.reconnectInterval); } } createError(err) { return new EventSourceError_1.EventSourceError(err, { readyState: this.eventSource.readyState, url: this.eventSource.url, eventsCount: this.eventSource._eventsCount, errorCount: this.errorCount, pingEventsCount: this.pingEventsCount, restartCount: this.restartCount, config: this.configuration, }); } addColossusPing() { if (this.eventSource) { this.eventSource.addEventListener('ping', this.checkPing); } } addMethods() { if (!this.eventSource) { return; } this.eventSource.onmessage = this.esOnMessage; this.eventSource.onopen = this.esOnOpen; this.eventSource.onerror = this.handleError; this.events.forEach(({ event, handler }) => { this.eventSource.addEventListener(event, handler); }); } checkPing() { this.pingEventsCount += 1; this.nRetries = 0; this.pingStatus = true; this.timerBeforeNextPing = setTimeout(() => { this.pingStatus = false; }, BEFORE_NEXT_PING); this.timerAfterNextPing = setTimeout(() => !this.pingStatus && this.reconnect(), AFTER_NEXT_PING); } clearTimers() { clearTimeout(this.timerBeforeNextPing); clearTimeout(this.timerAfterNextPing); } closeEventSource() { if (this.eventSource) { this.eventSource.close(); } } connectEventSource() { this.closeEventSource(); this.eventSource = new eventsource_1.default(this.source, this.configuration); } reconnect() { if (this.isClosed) { return; } this.restartCount += 1; this.connectEventSource(); this.addColossusPing(); this.addMethods(); } } exports.CustomEventSource = CustomEventSource;