From d0ed4e4c7ec6c1e558a4b67e7676eec75a38805d Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Sat, 20 Jun 2026 23:30:58 +0200 Subject: [PATCH] feat: Live-Metriken via WebSockets (Phase 3) --- routers/system.py | 15 ++++++++++++++- static/js/main.js | 25 ++++++++++++++++++++----- static/js/panels/jobs.js | 4 ++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/routers/system.py b/routers/system.py index 6e03ca7..a99338f 100644 --- a/routers/system.py +++ b/routers/system.py @@ -4,9 +4,10 @@ Greift lokal auf psutil und sysfs zu. """ from pathlib import Path +import asyncio import psutil -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, WebSocket, WebSocketDisconnect from auth import auth router = APIRouter(prefix="/api/system", dependencies=[Depends(auth)]) @@ -89,3 +90,15 @@ def system_status(): }, "gpu_temp": temps["gpu"] } + +@router.websocket("/stream") +async def system_stream(websocket: WebSocket): + await websocket.accept() + try: + while True: + # Sende Live-Daten alle 500ms + data = system_status() + await websocket.send_json(data) + await asyncio.sleep(0.5) + except WebSocketDisconnect: + pass diff --git a/static/js/main.js b/static/js/main.js index 67810aa..71dafd5 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -72,9 +72,24 @@ async function pollJobs() { catch { /* still */ } } -async function pollSystem() { - try { applySystem(await api("/api/system/status")); } - catch { /* still */ } +function connectSystemStream() { + const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; + const wsUrl = `${protocol}//${window.location.host}/api/system/stream`; + const ws = new WebSocket(wsUrl); + + ws.onmessage = (e) => { + try { + const data = JSON.parse(e.data); + applySystem(data); + } catch (err) {} + }; + + ws.onclose = () => { + // Bei Verbindungsabbruch nach 3 Sekunden erneut versuchen + setTimeout(connectSystemStream, 3000); + }; + + ws.onerror = () => ws.close(); } // ---- Boot ---- @@ -106,8 +121,8 @@ document.addEventListener("mc:refresh", pollStatus); pollStatus(); pollJobs(); -pollSystem(); +connectSystemStream(); + setInterval(tickClock, 1000); setInterval(pollStatus, 3000); setInterval(pollJobs, 1500); -setInterval(pollSystem, 2000); diff --git a/static/js/panels/jobs.js b/static/js/panels/jobs.js index 3e1aabc..e902154 100644 --- a/static/js/panels/jobs.js +++ b/static/js/panels/jobs.js @@ -34,9 +34,9 @@ function kvRow(k, v, cls = "") { return `
${k}${v}
`; } -// Chart-Daten (letzte 60 Sekunden, je 3s Polling = 20 Punkte) +// Chart-Daten (letzte 30 Sekunden, je 0.5s Stream = 60 Punkte) const hist = { cpu: [], ram: [], gpu: [] }; -const MAX_HIST = 20; +const MAX_HIST = 60; function renderSys() { if (!SYS) return;