UNPKG

@splitsoftware/splitio-commons

Version:
94 lines (93 loc) 4.35 kB
import { errorParser, messageParser } from './NotificationParser'; import { notificationKeeperFactory } from './NotificationKeeper'; import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, RB_SEGMENT_UPDATE } from '../constants'; import { STREAMING_PARSING_ERROR_FAILS, ERROR_STREAMING_SSE, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_NEW_MESSAGE } from '../../../logger/constants'; import { ABLY_ERROR, NON_REQUESTED, SSE_CONNECTION_ERROR } from '../../../utils/constants'; /** * Factory for SSEHandler, which processes SSEClient messages and emits the corresponding push events. * * @param log - factory logger * @param pushEmitter - emitter for events related to streaming support */ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) { var notificationKeeper = notificationKeeperFactory(pushEmitter, telemetryTracker); function isRetryableError(error) { if (error.parsedData && error.parsedData.code) { // Ably error var code = error.parsedData.code; telemetryTracker.streamingEvent(ABLY_ERROR, code); // 401 errors due to invalid or expired token (e.g., if refresh token coudn't be executed) if (40140 <= code && code <= 40149) return true; // Others 4XX errors (e.g., bad request from the SDK) if (40000 <= code && code <= 49999) return false; } else { // network errors or 5XX HTTP errors telemetryTracker.streamingEvent(SSE_CONNECTION_ERROR, NON_REQUESTED); } return true; } return { handleOpen: function () { notificationKeeper.handleOpen(); }, /* HTTP & Network errors */ handleError: function (error) { var errorWithParsedData = error; try { errorWithParsedData = errorParser(error); } catch (err) { log.warn(STREAMING_PARSING_ERROR_FAILS, [err]); } var errorMessage = (errorWithParsedData.parsedData && errorWithParsedData.parsedData.message) || errorWithParsedData.message; log.error(ERROR_STREAMING_SSE, [errorMessage]); if (isRetryableError(errorWithParsedData)) { pushEmitter.emit(PUSH_RETRYABLE_ERROR); } else { pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); } }, /* NotificationProcessor */ handleMessage: function (message) { var messageWithParsedData; try { messageWithParsedData = messageParser(message); if (!messageWithParsedData) return; // Messages with empty data are ignored } catch (err) { log.warn(STREAMING_PARSING_MESSAGE_FAILS, [err]); return; } var parsedData = messageWithParsedData.parsedData, data = messageWithParsedData.data, channel = messageWithParsedData.channel, timestamp = messageWithParsedData.timestamp; log.debug(STREAMING_NEW_MESSAGE, [data]); // we only handle update events if streaming is up if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(parsedData.type) === -1) return; switch (parsedData.type) { /* update events */ case SPLIT_UPDATE: case SEGMENT_UPDATE: case MEMBERSHIPS_MS_UPDATE: case MEMBERSHIPS_LS_UPDATE: case SPLIT_KILL: case RB_SEGMENT_UPDATE: pushEmitter.emit(parsedData.type, parsedData); break; /* occupancy & control events, handled by NotificationManagerKeeper */ case OCCUPANCY: notificationKeeper.handleOccupancyEvent(parsedData.metrics.publishers, channel, timestamp); break; case CONTROL: notificationKeeper.handleControlEvent(parsedData.controlType, channel, timestamp); break; default: break; } }, }; }