Skip to content

Commit

Permalink
do not keep retrying websoxket connection when it fails before sessio…
Browse files Browse the repository at this point in the history
…n established (#696)
  • Loading branch information
heswell authored May 15, 2023
1 parent f6a14c7 commit 5dc597f
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 18 deletions.
7 changes: 6 additions & 1 deletion vuu-ui/packages/vuu-data/src/connectionTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
export interface Connection<T = unknown> {
requiresLogin?: boolean;
send: (message: T) => void;
status: 'closed' | 'ready' | 'connected' | 'reconnected';
status:
| "closed"
| "ready"
| "connection-open-awaiting-session"
| "connected"
| "reconnected";
}
3 changes: 2 additions & 1 deletion vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Selection } from "@finos/vuu-datagrid-types";

export type ConnectionStatus =
| "connecting"
| "connection-open-awaiting-session"
| "connected"
| "disconnected"
| "reconnected";
Expand All @@ -42,7 +43,7 @@ export interface ConnectionQualityMetrics {
export const isConnectionQualityMetrics = (
msg: object
): msg is ConnectionQualityMetrics =>
(msg as ConnectionQualityMetrics).type === "connection-metrics"
(msg as ConnectionQualityMetrics).type === "connection-metrics";

export interface ServerProxySubscribeMessage {
aggregations: VuuAggregation[];
Expand Down
75 changes: 59 additions & 16 deletions vuu-ui/packages/vuu-data/src/websocket-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import {
import { Connection } from "./connectionTypes";
import { logger } from "@finos/vuu-utils";

import { ConnectionQualityMetrics, ConnectionStatus, ConnectionStatusMessage } from "./vuuUIMessageTypes";
import {
ConnectionQualityMetrics,
ConnectionStatus,
ConnectionStatusMessage,
} from "./vuuUIMessageTypes";

export type ConnectionMessage =
ServerToClientMessage | ConnectionStatusMessage | ConnectionQualityMetrics;
| ServerToClientMessage
| ConnectionStatusMessage
| ConnectionQualityMetrics;
export type ConnectionCallback = (msg: ConnectionMessage) => void;

const { debug, debugEnabled, error, info, warn } = logger(
Expand Down Expand Up @@ -68,7 +74,9 @@ async function makeConnection(
const websocketConnection =
connection ?? new WebsocketConnection(ws, url, callback);

const status = reconnecting ? "reconnected" : "connected";
const status = reconnecting
? "reconnected"
: "connection-open-awaiting-session";
callback({ type: "connection-status", status });
websocketConnection.status = status;

Expand Down Expand Up @@ -134,11 +142,19 @@ export class WebsocketConnection implements Connection<ClientToServerMessage> {
close: () => void = closeWarn;
requiresLogin = true;
send: (msg: ClientToServerMessage) => void = sendWarn;
status: "closed" | "ready" | "connected" | "reconnected" = "ready";
status:
| "closed"
| "ready"
| "connection-open-awaiting-session"
| "connected"
| "reconnected" = "ready";

public url: string;
public messagesCount = 0;

private connectionMetricsInterval: ReturnType<typeof setInterval> | null =
null;

constructor(ws: WebSocket, url: string, callback: ConnectionCallback) {
this.url = url;
this[connectionCallback] = callback;
Expand All @@ -152,20 +168,18 @@ export class WebsocketConnection implements Connection<ClientToServerMessage> {
[setWebsocket](ws: WebSocket) {
const callback = this[connectionCallback];
ws.onmessage = (evt) => {
const vuuMessageFromServer = parseMessage(evt.data);
this.messagesCount += 1;
if (process.env.NODE_ENV === "development") {
if (debugEnabled && vuuMessageFromServer.body.type !== "HB") {
debug?.(`<<< ${vuuMessageFromServer.body.type}`);
}
}
callback(vuuMessageFromServer);
this.status = "connected";
ws.onmessage = this.handleWebsocketMessage;
this.handleWebsocketMessage(evt);
};

setInterval(() => {
callback({ type: "connection-metrics", messagesLength: this.messagesCount });
this.connectionMetricsInterval = setInterval(() => {
callback({
type: "connection-metrics",
messagesLength: this.messagesCount,
});
this.messagesCount = 0;
}, 1000)
}, 1000);

ws.onerror = () => {
error(`⚡ connection error`);
Expand All @@ -174,7 +188,19 @@ export class WebsocketConnection implements Connection<ClientToServerMessage> {
status: "disconnected",
reason: "error",
});
if (this.status !== "closed") {

if (this.connectionMetricsInterval) {
clearInterval(this.connectionMetricsInterval);
this.connectionMetricsInterval = null;
}

if (this.status === "connection-open-awaiting-session") {
// our connection has errored before first server message has been received. This
// is not a normal reconnect, more likely a websocket configuration issue
error(
`Websocket connection lost before Vuu session established, check websocket configuration`
);
} else if (this.status !== "closed") {
reconnect(this);
this.send = queue;
}
Expand All @@ -187,6 +213,12 @@ export class WebsocketConnection implements Connection<ClientToServerMessage> {
status: "disconnected",
reason: "close",
});

if (this.connectionMetricsInterval) {
clearInterval(this.connectionMetricsInterval);
this.connectionMetricsInterval = null;
}

if (this.status !== "closed") {
reconnect(this);
this.send = queue;
Expand Down Expand Up @@ -216,4 +248,15 @@ export class WebsocketConnection implements Connection<ClientToServerMessage> {
info?.("close websocket");
};
}

handleWebsocketMessage = (evt) => {
const vuuMessageFromServer = parseMessage(evt.data);
this.messagesCount += 1;
if (process.env.NODE_ENV === "development") {
if (debugEnabled && vuuMessageFromServer.body.type !== "HB") {
debug?.(`<<< ${vuuMessageFromServer.body.type}`);
}
}
this[connectionCallback](vuuMessageFromServer);
};
}

0 comments on commit 5dc597f

Please sign in to comment.