Speed up server list & detail loads
All checks were successful
Deploy GSM / deploy (push) Successful in 28s

Three compounding causes made the dashboard and detail pages slow:

- Detail page fetched the WHOLE fleet (every SSH/Prometheus/RCON call for
  all servers) just to show one. Switch ServerDetail to GET /servers/:id
  (add api.getServer) so it costs one server's worth of work, not N.
- No server-side caching: every 10s poll, from every open tab, recomputed
  everything. Add a shared 5s-TTL per-server cache + in-flight dedup behind
  both GET / and GET /:id; invalidate on start/stop/restart so power
  actions still reflect immediately.
- Prometheus fetch had no timeout, so a slow/restarting Prometheus hung the
  whole aggregation indefinitely (the .catch can't catch a hang). Add
  AbortSignal.timeout to queryPrometheus/queryPrometheusRange.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-26 13:46:34 +02:00
parent 2f6fc841b2
commit 024d97e544
4 changed files with 134 additions and 148 deletions

View File

@@ -1,6 +1,10 @@
import fetch from "node-fetch";
const PROMETHEUS_URL = "http://localhost:9090";
// Without a timeout a slow/restarting Prometheus makes fetch() hang forever; the
// surrounding .catch() can't help because a hung request never rejects. Abort
// after a few seconds so the status aggregation can't stall on Prometheus.
const PROMETHEUS_TIMEOUT_MS = 4000;
const SERVER_JOBS = {
"vrising": "vrising",
@@ -16,7 +20,7 @@ const SERVER_JOBS = {
export async function queryPrometheus(query) {
const url = `${PROMETHEUS_URL}/api/v1/query?query=${encodeURIComponent(query)}`;
const res = await fetch(url);
const res = await fetch(url, { signal: AbortSignal.timeout(PROMETHEUS_TIMEOUT_MS) });
const data = await res.json();
if (data.status !== "success") {
throw new Error(`Prometheus query failed: ${data.error}`);
@@ -26,7 +30,7 @@ export async function queryPrometheus(query) {
export async function queryPrometheusRange(query, start, end, step) {
const url = `${PROMETHEUS_URL}/api/v1/query_range?query=${encodeURIComponent(query)}&start=${start}&end=${end}&step=${step}`;
const res = await fetch(url);
const res = await fetch(url, { signal: AbortSignal.timeout(PROMETHEUS_TIMEOUT_MS) });
const data = await res.json();
if (data.status !== "success") {
throw new Error(`Prometheus query failed: ${data.error}`);