@eclipse-ditto/ditto-javascript-client-dom
Version:
DOM implementation of Eclipse Ditto JavaScript API to be used in browsers.
213 lines • 7.47 kB
JavaScript
/*!
* 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