UNPKG

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

Version:

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

226 lines 6.73 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 { bufferFullError } from './websocket-resilience-interfaces'; /** * A class to buffer Messages. */ export class ResilienceMessageBuffer { constructor(maxBufferSize) { this.maxBufferSize = maxBufferSize; this.messages = new Map(); } /** * Adds a message to the buffer. * * @param message - The message to buffer. * @returns A Promise that resolves once the message was sent */ addMessage(message) { if (this.full()) { throw Error('The buffer is full!'); } return new Promise((resolve, reject) => { const storedMessage = this.messages.get(message); if (storedMessage) { storedMessage.resolve.push(resolve); storedMessage.reject.push(reject); } else { this.messages.set(message, { resolve: [resolve], reject: [reject] }); } }); } /** * Sends the messages from the buffer and resolves their promises. * * @param webSocket - The web socket to send the messages on. * @returns Whether all messages were successfully sent or not */ sendMessages(webSocket) { try { const outstandingMessages = new Map(this.messages); outstandingMessages.forEach((response, message) => { webSocket.executeCommand(message); response.resolve.forEach(resolve => resolve()); this.messages.delete(message); }); } catch (e) { return false; } return this.empty(); } /** * Rejects the Promises for all messages in the buffer and clears it. * * @param reason - The reason to reject the Promises with. */ rejectMessages(reason) { this.messages.forEach(response => response.reject.forEach(reject => reject(reason))); this.messages.clear(); } /** * Calculates whether the buffer is full. * * @returns Whether the buffer is full */ full() { if (this.maxBufferSize === undefined) { return true; } return this.size >= this.maxBufferSize; } /** * Calculates the number of messages in the buffer. * * @returns The number of messages in the buffer */ get size() { let size = 0; this.messages.forEach(information => size += information.resolve.length); return size; } /** * Calculates whether the buffer is empty. * * @returns Whether the buffer is empty */ empty() { return this.messages.size === 0; } } /** * A class to buffer requests that expect a response. */ export class ResilienceRequestBuffer { constructor(maxBufferSize) { this.maxBufferSize = maxBufferSize; this.requests = new Map(); this.outstanding = []; this.polling = []; } /** * Stores a request that is waiting for a response. * * @param id - The correlation-id of the request. * @param request - The request to be stored. */ addRequest(id, request) { this.requests.set(id, request); } /** * Adds a request to the buffer. * * @param id - The id of the request to buffer. * @param rejectionHandler - The method to use if the request needs to be rejected. * @returns Whether the request was successfully buffered or not */ addOutstanding(id, rejectionHandler) { if (this.full()) { rejectionHandler(bufferFullError); return false; } if (this.polling.indexOf(id) >= 0) { this.removeFromArray(id, this.polling); } else { this.outstanding.push(id); } return true; } /** * Sends the first element of the buffer that is not currently waiting for a response. * * @param webSocket - The web socket to send the requests on. * @returns Whether a request was successfully sent or not */ sendNextOutstanding(webSocket) { if (this.outstanding.length === this.polling.length) { return false; } if (this.outstanding.length !== 0) { let id; for (id of this.outstanding) { if (this.polling.indexOf(id) < 0) { this.polling.push(id); // @ts-ignore webSocket.executeCommand(this.requests.get(id)); return true; } } } return false; } /** * Rejects all requests in the buffer. * * @param rejectionHandler - The method to use to reject the requests. */ rejectAllOngoing(rejectionHandler) { this.requests.forEach((_, id) => { rejectionHandler(id); this.deleteRequest(id); }); } /** * Deletes a request from the buffer. * * @param id - The id of the request to delete. */ deleteRequest(id) { this.removeFromArray(id, this.outstanding); this.removeFromArray(id, this.polling); this.requests.delete(id); } /** * Removes a request from an array. * * @param id - The id of the request to delete. * @param array - The array to delete the request from. */ removeFromArray(id, array) { const index = array.indexOf(id); if (index >= 0) { array.splice(index, 1); } } /** * Checks whether a buffered request is currently waiting for response. * * @param id - The id of the message. * @returns Whether the request is polling or not */ isPolling(id) { return this.polling.indexOf(id) >= 0; } /** * Checks whether the buffer is empty. * * @returns Whether the buffer is empty or not */ empty() { return this.outstanding.length === 0; } /** * Checks whether the buffer is full. * * @returns Whether the buffer is full or not */ full() { if (this.maxBufferSize === undefined) { return true; } return this.outstanding.length >= this.maxBufferSize; } } //# sourceMappingURL=websocket-resilience-buffer.js.map