Automatic reconnect to server with exp backoff

This commit is contained in:
Radon Rosborough 2020-06-07 16:24:45 -06:00
parent b31e49d40d
commit 76a1c8fa1d
1 changed files with 63 additions and 46 deletions

View File

@ -14,56 +14,73 @@ term.open(document.getElementById("terminal"));
fitAddon.fit(); fitAddon.fit();
window.addEventListener("resize", () => fitAddon.fit()); window.addEventListener("resize", () => fitAddon.fit());
const socket = new WebSocket( const initialRetryDelayMs = 200;
(document.location.protocol === "http:" ? "ws://" : "wss://") + let retryDelayMs = initialRetryDelayMs;
document.location.host +
`/api/v1/ws?lang=${lang}`
);
socket.addEventListener("open", () => function tryConnect() {
console.log("Successfully connected to server") console.log("Connecting to server...");
); socket = new WebSocket(
socket.addEventListener("message", (event) => { (document.location.protocol === "http:" ? "ws://" : "wss://") +
let message: any; document.location.host +
try { `/api/v1/ws?lang=${lang}`
message = JSON.parse(event.data); );
} catch (err) { socket.addEventListener("open", () => {
console.error("Malformed message from server:", event.data); retryDelayMs = initialRetryDelayMs;
return; console.log("Successfully connected to server");
} });
switch (message?.event) { socket.addEventListener("message", (event: MessageEvent) => {
case "terminalClear": let message: any;
term.reset(); try {
message = JSON.parse(event.data);
} catch (err) {
console.error("Malformed message from server:", event.data);
return; return;
case "terminalOutput": }
if (typeof message.output !== "string") { switch (message?.event) {
case "terminalClear":
term.reset();
return;
case "terminalOutput":
if (typeof message.output !== "string") {
console.error("Unexpected message from server:", message);
return;
}
term.write(message.output);
return;
case "setMonacoLanguage":
if (typeof message.monacoLanguage !== "string") {
console.error("Unexpected message from server:", message);
return;
}
monaco.editor.setModelLanguage(
editor.getModel(),
message.monacoLanguage
);
return;
default:
console.error("Unexpected message from server:", message); console.error("Unexpected message from server:", message);
return; return;
} }
term.write(message.output); });
return; socket.addEventListener("close", (event: CloseEvent) => {
case "setMonacoLanguage": if (event.wasClean) {
if (typeof message.monacoLanguage !== "string") { console.log("Connection closed cleanly");
console.error("Unexpected message from server:", message); } else {
return; console.error("Connection died");
} }
monaco.editor.setModelLanguage(editor.getModel(), message.monacoLanguage); scheduleConnect();
return; });
default: }
console.error("Unexpected message from server:", message);
return; function scheduleConnect() {
} const delay = retryDelayMs * Math.random();
}); console.log(`Trying to reconnect in ${Math.floor(delay)}ms`);
socket.addEventListener("close", (event) => { setTimeout(tryConnect, delay);
if (event.wasClean) { retryDelayMs *= 2;
console.log("Connection closed cleanly"); }
} else {
console.error("Connection died"); let socket = null;
} tryConnect();
});
socket.addEventListener("onerror", (event) =>
console.error("Connection error:", event)
);
term.onData((data) => term.onData((data) =>
socket.send(JSON.stringify({ event: "terminalInput", input: data })) socket.send(JSON.stringify({ event: "terminalInput", input: data }))