UNPKG

@launchdarkly/js-server-sdk-common

Version:
110 lines 5.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const js_sdk_common_1 = require("@launchdarkly/js-sdk-common"); const reportJsonError = (type, data, logger, errorHandler) => { logger === null || logger === void 0 ? void 0 : logger.error(`Stream received invalid data in "${type}" message`); logger === null || logger === void 0 ? void 0 : logger.debug(`Invalid JSON follows: ${data}`); errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(new js_sdk_common_1.LDStreamingError(js_sdk_common_1.DataSourceErrorKind.InvalidData, 'Malformed JSON data in event stream')); }; class StreamingProcessor { constructor(clientContext, streamUriPath, parameters, _listeners, baseHeaders, _diagnosticsManager, _errorHandler, _streamInitialReconnectDelay = 1) { this._listeners = _listeners; this._diagnosticsManager = _diagnosticsManager; this._errorHandler = _errorHandler; this._streamInitialReconnectDelay = _streamInitialReconnectDelay; const { basicConfiguration, platform } = clientContext; const { logger } = basicConfiguration; const { requests } = platform; this._headers = Object.assign({}, baseHeaders); this._logger = logger; this._requests = requests; this._streamUri = (0, js_sdk_common_1.getStreamingUri)(basicConfiguration.serviceEndpoints, streamUriPath, parameters); } _logConnectionStarted() { this._connectionAttemptStartTime = Date.now(); } _logConnectionResult(success) { if (this._connectionAttemptStartTime && this._diagnosticsManager) { this._diagnosticsManager.recordStreamInit(this._connectionAttemptStartTime, !success, Date.now() - this._connectionAttemptStartTime); } this._connectionAttemptStartTime = undefined; } /** * This is a wrapper around the passed errorHandler which adds additional * diagnostics and logging logic. * * @param err The error to be logged and handled. * @return boolean whether to retry the connection. * * @private */ _retryAndHandleError(err) { var _a, _b, _c; if (!(0, js_sdk_common_1.shouldRetry)(err)) { this._logConnectionResult(false); (_a = this._errorHandler) === null || _a === void 0 ? void 0 : _a.call(this, new js_sdk_common_1.LDStreamingError(js_sdk_common_1.DataSourceErrorKind.ErrorResponse, err.message, err.status)); (_b = this._logger) === null || _b === void 0 ? void 0 : _b.error((0, js_sdk_common_1.httpErrorMessage)(err, 'streaming request')); return false; } (_c = this._logger) === null || _c === void 0 ? void 0 : _c.warn((0, js_sdk_common_1.httpErrorMessage)(err, 'streaming request', 'will retry')); this._logConnectionResult(false); this._logConnectionStarted(); return true; } start() { this._logConnectionStarted(); // TLS is handled by the platform implementation. const eventSource = this._requests.createEventSource(this._streamUri, { headers: this._headers, errorFilter: (error) => this._retryAndHandleError(error), initialRetryDelayMillis: 1000 * this._streamInitialReconnectDelay, readTimeoutMillis: 5 * 60 * 1000, retryResetIntervalMillis: 60 * 1000, }); this._eventSource = eventSource; eventSource.onclose = () => { var _a; (_a = this._logger) === null || _a === void 0 ? void 0 : _a.info('Closed LaunchDarkly stream connection'); }; eventSource.onerror = () => { // The work is done by `errorFilter`. }; eventSource.onopen = () => { var _a; (_a = this._logger) === null || _a === void 0 ? void 0 : _a.info('Opened LaunchDarkly stream connection'); }; eventSource.onretrying = (e) => { var _a; (_a = this._logger) === null || _a === void 0 ? void 0 : _a.info(`Will retry stream connection in ${e.delayMillis} milliseconds`); }; this._listeners.forEach(({ deserializeData, processJson }, eventName) => { eventSource.addEventListener(eventName, (event) => { var _a, _b; (_a = this._logger) === null || _a === void 0 ? void 0 : _a.debug(`Received ${eventName} event`); if (event === null || event === void 0 ? void 0 : event.data) { this._logConnectionResult(true); const { data } = event; const dataJson = deserializeData(data); if (!dataJson) { reportJsonError(eventName, data, this._logger, this._errorHandler); return; } processJson(dataJson); } else { (_b = this._errorHandler) === null || _b === void 0 ? void 0 : _b.call(this, new js_sdk_common_1.LDStreamingError(js_sdk_common_1.DataSourceErrorKind.Unknown, 'Unexpected payload from event stream')); } }); }); } stop() { var _a; (_a = this._eventSource) === null || _a === void 0 ? void 0 : _a.close(); this._eventSource = undefined; } close() { this.stop(); } } exports.default = StreamingProcessor; //# sourceMappingURL=StreamingProcessor.js.map