Skip to content

Commit

Permalink
[protocol] Trigger onClose/onOpen whenever the underlying websocket O…
Browse files Browse the repository at this point in the history
…PEN/CLOSEs.
  • Loading branch information
geropl authored and roboquat committed Sep 28, 2021
1 parent 67b311c commit cc29602
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 15 deletions.
28 changes: 19 additions & 9 deletions components/gitpod-protocol/src/messaging/browser/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
*/

import { Logger, ConsoleLogger, toSocket, IWebSocket } from "vscode-ws-jsonrpc";
import { MessageConnection, createMessageConnection } from "vscode-jsonrpc";
import { createMessageConnection } from "vscode-jsonrpc";
import { AbstractMessageWriter } from "vscode-jsonrpc/lib/messageWriter";
import { AbstractMessageReader } from "vscode-jsonrpc/lib/messageReader";
import { JsonRpcProxyFactory, JsonRpcProxy } from "../proxy-factory";
import { ConnectionHandler } from "../handler";
import { ConnectionEventHandler, ConnectionHandler } from "../handler";
import ReconnectingWebSocket, { Event } from 'reconnecting-websocket';

export interface WebSocketOptions {
Expand All @@ -32,7 +32,10 @@ export class WebSocketConnectionProvider {
const startListening = (path: string) => {
const socket = this.listen({
path,
onConnection: c => factory.listen(c)
onConnection: c => factory.listen(c),
}, {
onTransportDidClose: () => factory.fireConnectionClosed(),
onTransportDidOpen: () => factory.fireConnectionOpened(),
},
options
);
Expand All @@ -52,7 +55,7 @@ export class WebSocketConnectionProvider {
/**
* Install a connection handler for the given path.
*/
listen(handler: ConnectionHandler, options?: WebSocketOptions): WebSocket {
listen(handler: ConnectionHandler, eventHandler: ConnectionEventHandler, options?: WebSocketOptions): WebSocket {
const url = handler.path;
const webSocket = this.createWebSocket(url);

Expand All @@ -69,7 +72,8 @@ export class WebSocketConnectionProvider {
}
doListen(
webSocket as any as ReconnectingWebSocket,
connection => handler.onConnection(connection),
handler,
eventHandler,
logger,
);
return webSocket;
Expand Down Expand Up @@ -100,16 +104,22 @@ export class WebSocketConnectionProvider {
// - webSocket.onopen: making sure it's only ever called once so we're re-using MessageConnection
// - WebSocketMessageWriter: buffer and re-try messages instead of throwing an error immidiately
// - WebSocketMessageReader: don't close MessageConnection on 'socket.onclose'
function doListen(resocket: ReconnectingWebSocket, onConnection: (connection: MessageConnection) => void, logger: Logger) {
function doListen(resocket: ReconnectingWebSocket, handler: ConnectionHandler, eventHandler: ConnectionEventHandler, logger: Logger) {
resocket.addEventListener("close", () => eventHandler.onTransportDidClose());

let alreadyOpened = false;
resocket.onopen = () => {
// trigerr "open" every time we re-open the underlying websocket
eventHandler.onTransportDidOpen();

// make sure we're only ever creating one MessageConnection, irregardless of how many times we have to re-open the underlying (reconnecting) websocket
if (alreadyOpened) {
return;
}
alreadyOpened = true;

const connection = createWebSocketConnection(resocket, logger);
onConnection(connection);
handler.onConnection(connection);
};
}

Expand Down Expand Up @@ -167,12 +177,12 @@ class BufferingWebSocketMessageWriter extends AbstractMessageWriter {
for (const msg of buffer) {
this.write(msg);
}
this.logger.info(`flushed buffer (${this.buffer.length})`)
//this.logger.info(`flushed buffer (${this.buffer.length})`)
}

protected bufferMsg(msg: any) {
this.buffer.push(msg);
this.logger.info(`buffered message (${this.buffer.length})`);
//this.logger.info(`buffered message (${this.buffer.length})`);
}
}

Expand Down
12 changes: 12 additions & 0 deletions components/gitpod-protocol/src/messaging/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,15 @@ export interface ConnectionHandler {
readonly path: string;
onConnection(connection: MessageConnection, session?: object): void;
}

export interface ConnectionEventHandler {
/**
* Called when the transport underpinning the connection got closed
*/
onTransportDidClose(): void;

/**
* Called when the transport underpinning the connection is (re-)opened
*/
onTransportDidOpen(): void;
}
14 changes: 8 additions & 6 deletions components/gitpod-protocol/src/messaging/proxy-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
this.connectionPromise = new Promise(resolve =>
this.connectionPromiseResolve = resolve
);
this.connectionPromise.then(connection => {
connection.onClose(() =>
this.onDidCloseConnectionEmitter.fire(undefined)
);
this.onDidOpenConnectionEmitter.fire(undefined);
});
}

fireConnectionClosed() {
this.onDidCloseConnectionEmitter.fire(undefined)
}

fireConnectionOpened() {
this.onDidOpenConnectionEmitter.fire(undefined);
}

/**
Expand Down

0 comments on commit cc29602

Please sign in to comment.