From c842513116a1ac7d8435d2af316e833eeaa4d489 Mon Sep 17 00:00:00 2001 From: Alexander Zielonka Date: Sun, 21 Jun 2026 20:17:03 +0200 Subject: [PATCH] Report unreachable hosts consistently so dashboard stops flapping getServerStatus returned 'offline' for both a stopped server AND an unreachable host. The dashboard hides 'unreachable' but shows 'offline', so an off VM oscillated in/out of the list as the failed-host breaker expired and re-tripped. Now distinguish: connection failure/hang -> 'unreachable' (host down), reachable-but-process-stopped -> 'offline'. Both autoshutdown and the Discord bot already treat non-online as not running. Co-Authored-By: Claude Opus 4.8 (1M context) --- gsm-backend/services/ssh.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gsm-backend/services/ssh.js b/gsm-backend/services/ssh.js index 3d0ec82..12d744a 100644 --- a/gsm-backend/services/ssh.js +++ b/gsm-backend/services/ssh.js @@ -83,8 +83,10 @@ async function getConnection(host, username = "root") { // Returns: "online", "starting", "stopping", "offline" export async function getServerStatus(server) { const connKey = (server.sshUser || "root") + "@" + server.host; + let connected = false; const check = (async () => { const ssh = await getConnection(server.host, server.sshUser); + connected = true; if (server.runtime === 'docker') { const result = await ssh.execCommand(`docker inspect --format='{{.State.Status}}' ${server.containerName} 2>/dev/null`); @@ -141,8 +143,13 @@ export async function getServerStatus(server) { // Connection hung (host likely powered off mid-session) -> drop it and trip the breaker sshConnections.delete(connKey); markHostFailed(server.host, server.sshUser); + return 'unreachable'; } - return 'offline'; + // Couldn't reach the host at all -> "unreachable" so the dashboard hides it + // consistently, instead of flapping to "offline" every time the failed-host + // breaker expires and a fresh connect is attempted. Reachable but the runtime + // command failed -> "offline". + return connected ? 'offline' : 'unreachable'; } }