UNPKG

@eclipse-ditto/ditto-javascript-client-dom

Version:

DOM implementation of Eclipse Ditto JavaScript API to be used in browsers.

213 lines 7.47 kB
/*! * Copyright (c) 2019 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 */ import { DefaultDittoProtocolResponse } from '../../../model/ditto-protocol'; /** * An abstract factory that builds ResilienceHandlers. */ export class ResilienceHandlerFactory { withContext(webSocketBuilder, stateHandler) { this.webSocketBuilder = webSocketBuilder; this.stateHandler = stateHandler; return this; } } export var WebSocketBindingMessage; (function (WebSocketBindingMessage) { WebSocketBindingMessage["START_SEND_EVENTS"] = "START-SEND-EVENTS"; WebSocketBindingMessage["STOP_SEND_EVENTS"] = "STOP-SEND-EVENTS"; WebSocketBindingMessage["START_SEND_MESSAGES"] = "START-SEND-MESSAGES"; WebSocketBindingMessage["STOP_SEND_MESSAGES"] = "STOP-SEND-MESSAGES"; WebSocketBindingMessage["START_SEND_LIVE_COMMANDS"] = "START-SEND-LIVE-COMMANDS"; WebSocketBindingMessage["STOP_SEND_LIVE_COMMANDS"] = "STOP-SEND-LIVE-COMMANDS"; WebSocketBindingMessage["START_SEND_LIVE_EVENTS"] = "START-SEND-LIVE-EVENTS"; WebSocketBindingMessage["STOP_SEND_LIVE_EVENTS"] = "STOP-SEND-LIVE-EVENTS"; })(WebSocketBindingMessage || (WebSocketBindingMessage = {})); export class AbstractResilienceHandler { constructor(stateHandler, requestHandler) { this.requestHandler = requestHandler; this.protocolMessages = new Map(); this.stateHandler = new ResilienceStateHandler(ConnectionState.Connecting, stateHandler); } static isWebSocketBindingMessage(message) { return message.endsWith(':ACK'); } handleInput(input) { if (AbstractResilienceHandler.isWebSocketBindingMessage(input)) { this.handleWebSocketBindingMessage(input); return; } const response = DefaultDittoProtocolResponse.fromJson(input); if (response.correlationId() !== undefined) { this.handleResponse(response.correlationId(), response); } else { this.handleMessage(response); } } sendProtocolMessage(message) { return new Promise((resolve, reject) => { this.protocolMessages.set(message, { resolve, reject }); this.send(message) .catch(error => { reject(error); this.protocolMessages.delete(message); }); }); } handleWebSocketBindingMessage(message) { this.protocolMessages.get(message.replace(':ACK', '')).resolve(); } handleMessage(message) { this.requestHandler.handleMessage(message); } handleClose(promise) { this.stateHandler.reconnecting(); this.rejectAllOngoing(connectionInterruptedError); this.resolveWebSocket(promise); } handleError(error) { console.error(error); } } /** * No-op implementation of WebSocketStateHandler. */ export class NoopWebSocketStateHandler { backPressure() { } bufferFull() { } buffering() { } connected() { } disconnected() { } reconnecting() { } } export const connectionUnavailableError = { status: 0, error: 'connection.unavailable', message: 'The websocket is not connected.', description: 'The websocket connection to the server failed.' }; export const connectionInterruptedError = { status: 1, error: 'connection.interrupted', message: 'The websocket connection to the server was interrupted.', description: 'The request might have been sent and processed.' }; export const connectionLostError = { status: 2, error: 'connection.lost', message: 'The websocket connection to the server was lost.', description: 'The reconnection to the server was unsuccessful.' }; export const bufferFullError = { status: 3, error: 'buffer.overflow', message: 'The buffer limit is reached.', description: 'You can set a higher buffer size to buffer more requests.' }; /** * A handler to keep track of the state of a connection and to communicate changes to it. */ export class ResilienceStateHandler { constructor(state, stateHandler) { this.state = state; this.stateHandler = stateHandler; } /** * Checks whether a buffer is used. * * @returns Whether a buffer is used */ isBuffering() { return this.state >= ConnectionState.Buffering; } /** * Checks whether the connection is still working or completely disconnected. * * @returns Whether the connection is still working */ isWorking() { return this.state < ConnectionState.Disconnected; } /** * Checks whether the connection is able to send requests. * * @returns Whether the connection is able to send requests */ canSend() { return this.state < ConnectionState.BackPressure; } /** * Checks whether the connection is connected and not using a buffer. * * @returns Whether the connection is connected and not using a buffer */ isConnected() { return this.state === ConnectionState.Connected; } connected() { if (this.state !== ConnectionState.Connected && this.state !== ConnectionState.Disconnected) { this.state = ConnectionState.Connected; this.stateHandler.connected(); } } buffering() { if (this.state !== ConnectionState.Buffering && this.state !== ConnectionState.Disconnected) { this.state = ConnectionState.Buffering; this.stateHandler.buffering(); } } backPressure() { if (this.state < ConnectionState.BackPressure) { this.state = ConnectionState.BackPressure; this.stateHandler.backPressure(); } } reconnecting() { if (this.state < ConnectionState.Reconnecting) { this.state = ConnectionState.Reconnecting; this.stateHandler.reconnecting(); } } bufferFull() { if (this.state !== ConnectionState.BufferFull && this.state !== ConnectionState.Disconnected) { this.state = ConnectionState.BufferFull; this.stateHandler.bufferFull(); } } disconnected() { if (this.state !== ConnectionState.Disconnected) { this.state = ConnectionState.Disconnected; this.stateHandler.disconnected(); } } } /** * An enum containing the different states a connection can be in. */ export var ConnectionState; (function (ConnectionState) { ConnectionState[ConnectionState["Connected"] = 0] = "Connected"; ConnectionState[ConnectionState["Buffering"] = 1] = "Buffering"; ConnectionState[ConnectionState["BackPressure"] = 2] = "BackPressure"; ConnectionState[ConnectionState["Reconnecting"] = 3] = "Reconnecting"; ConnectionState[ConnectionState["Connecting"] = 3] = "Connecting"; ConnectionState[ConnectionState["BufferFull"] = 4] = "BufferFull"; ConnectionState[ConnectionState["Disconnected"] = 5] = "Disconnected"; })(ConnectionState || (ConnectionState = {})); //# sourceMappingURL=websocket-resilience-interfaces.js.map