diff --git a/app/src/js/scrollback.ts b/app/src/js/scrollback.ts index de3607f..b465a6d 100644 --- a/app/src/js/scrollback.ts +++ b/app/src/js/scrollback.ts @@ -3,6 +3,7 @@ // input, output, etc import { scrollback, $$ } from "./dom.js" +import { randomId } from "../shared/utils.js" import type { CommandOutput } from "../shared/types.js" type InputStatus = "waiting" | "streaming" | "ok" | "error" @@ -48,7 +49,7 @@ export function setStatus(id: string, status: InputStatus) { export function addOutput(id: string, output: CommandOutput) { const item = $$("li") item.classList.add("output") - item.dataset.id = id + item.dataset.id = id || randomId() const [format, content] = processOutput(output) @@ -61,6 +62,10 @@ export function addOutput(id: string, output: CommandOutput) { autoScroll() } +export function addErrorMessage(message: string) { + addOutput("", { html: `${message}` }) +} + export function appendOutput(id: string, output: CommandOutput) { const item = document.querySelector(`[data-id="${id}"].output`) diff --git a/app/src/js/websocket.ts b/app/src/js/websocket.ts index 3cd018e..7d82304 100644 --- a/app/src/js/websocket.ts +++ b/app/src/js/websocket.ts @@ -4,6 +4,10 @@ import type { Message } from "../shared/types.js" import { sessionID } from "./session.js" import { handleMessage } from "./shell.js" +import { addErrorMessage } from "./scrollback.js" + +const MAX_RETRIES = 5 +let retries = 0 let ws: WebSocket | null = null @@ -14,7 +18,7 @@ export function startConnection() { ws = new WebSocket(url) ws.onmessage = receive - ws.onclose = () => setTimeout(startConnection, 1000) // simple retry + ws.onclose = retryConnection ws.onerror = () => ws?.close() } @@ -36,3 +40,13 @@ export function close() { ws?.close(1000, 'bye') } +function retryConnection() { + if (retries >= MAX_RETRIES) { + addErrorMessage(`!! Failed to reconnect ${retries} times. Server is down.`) + if (ws) ws.onclose = () => { } + return + } + retries++ + addErrorMessage(`!! Connection lost. Retrying...`) + setTimeout(startConnection, 1000) +}