From 9727e53e353664308f4b6e26fe1ce45f4fd82ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Sun, 22 Mar 2026 19:12:00 +0100 Subject: [PATCH] Ergaenze Statusuebersicht um Summenwerte Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- docs/PLAYER-STATUS-HTTP.md | 3 ++ .../backend/internal/httpapi/playerstatus.go | 13 ++++++++ .../internal/httpapi/playerstatus_test.go | 33 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/docs/PLAYER-STATUS-HTTP.md b/docs/PLAYER-STATUS-HTTP.md index aaa853d..bd04909 100644 --- a/docs/PLAYER-STATUS-HTTP.md +++ b/docs/PLAYER-STATUS-HTTP.md @@ -76,6 +76,7 @@ Zusätzlich zur Write-Route gibt es in dieser Stufe: `GET /api/v1/screens/status` liefert eine kleine Uebersicht aller bisher berichtenden Screens mit ihrem jeweils letzten bekannten Datensatz. Die Rueckgabe wird aktuell fuer Diagnosezwecke priorisiert sortiert: zuerst `offline`, dann `degraded`, dann `online`, innerhalb derselben Gruppe nach `screen_id`. +Zusaetzlich enthaelt die Antwort eine `summary` mit kompakten Counts fuer `total`, `online`, `degraded`, `offline` und `stale`. Aktuell unterstuetzte Query-Parameter fuer die Uebersicht: @@ -84,6 +85,8 @@ Aktuell unterstuetzte Query-Parameter fuer die Uebersicht: - `updated_since=` zum Filtern nach `received_at` - `limit=` zum Begrenzen der Anzahl zurueckgelieferter Screens +Die Query-Parameter beeinflussen die Liste in `screens`; die `summary` beschreibt weiterhin den gesamten aktuell bekannten Statusbestand. + `GET /api/v1/screens/{screenId}/status` liefert den zuletzt akzeptierten Status fuer einen einzelnen Screen zurueck. Wenn fuer den Screen noch kein Status vorliegt, liefert das Backend `404` mit dem gemeinsamen Fehlerumschlag. diff --git a/server/backend/internal/httpapi/playerstatus.go b/server/backend/internal/httpapi/playerstatus.go index 3f36790..88e54ca 100644 --- a/server/backend/internal/httpapi/playerstatus.go +++ b/server/backend/internal/httpapi/playerstatus.go @@ -144,9 +144,21 @@ func handleListLatestPlayerStatuses(store playerStatusStore) http.HandlerFunc { return } filtered := make([]playerStatusRecord, 0, len(records)) + summary := map[string]int{ + "total": 0, + "online": 0, + "degraded": 0, + "offline": 0, + "stale": 0, + } for i := range records { records[i].Stale = isStale(records[i], store.Now()) records[i].DerivedState = deriveState(records[i]) + summary["total"]++ + summary[records[i].DerivedState]++ + if records[i].Stale { + summary["stale"]++ + } if updatedSince != nil && !isUpdatedSince(records[i], *updatedSince) { continue } @@ -179,6 +191,7 @@ func handleListLatestPlayerStatuses(store playerStatusStore) http.HandlerFunc { } writeJSON(w, http.StatusOK, map[string]any{ + "summary": summary, "screens": filtered, }) } diff --git a/server/backend/internal/httpapi/playerstatus_test.go b/server/backend/internal/httpapi/playerstatus_test.go index c5ea87d..49af99a 100644 --- a/server/backend/internal/httpapi/playerstatus_test.go +++ b/server/backend/internal/httpapi/playerstatus_test.go @@ -426,6 +426,13 @@ func TestHandleListLatestPlayerStatuses(t *testing.T) { } var response struct { + Summary struct { + Total int `json:"total"` + Online int `json:"online"` + Degraded int `json:"degraded"` + Offline int `json:"offline"` + Stale int `json:"stale"` + } `json:"summary"` Screens []playerStatusRecord `json:"screens"` } if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { @@ -443,6 +450,10 @@ func TestHandleListLatestPlayerStatuses(t *testing.T) { if got, want := response.Screens[1].ScreenID, "screen-b"; got != want { t.Fatalf("response.Screens[1].ScreenID = %q, want %q", got, want) } + + if got, want := response.Summary.Total, 2; got != want { + t.Fatalf("response.Summary.Total = %d, want %d", got, want) + } } func TestHandleListLatestPlayerStatusesOrdersProblematicScreensFirst(t *testing.T) { @@ -460,6 +471,13 @@ func TestHandleListLatestPlayerStatusesOrdersProblematicScreensFirst(t *testing. handleListLatestPlayerStatuses(store)(w, req) var response struct { + Summary struct { + Total int `json:"total"` + Online int `json:"online"` + Degraded int `json:"degraded"` + Offline int `json:"offline"` + Stale int `json:"stale"` + } `json:"summary"` Screens []playerStatusRecord `json:"screens"` } if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { @@ -497,6 +515,13 @@ func TestHandleListLatestPlayerStatusesFiltersByConnectivityAndStale(t *testing. } var response struct { + Summary struct { + Total int `json:"total"` + Online int `json:"online"` + Degraded int `json:"degraded"` + Offline int `json:"offline"` + Stale int `json:"stale"` + } `json:"summary"` Screens []playerStatusRecord `json:"screens"` } if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { @@ -510,6 +535,14 @@ func TestHandleListLatestPlayerStatusesFiltersByConnectivityAndStale(t *testing. if got, want := response.Screens[0].ScreenID, "screen-offline"; got != want { t.Fatalf("response.Screens[0].ScreenID = %q, want %q", got, want) } + + if got, want := response.Summary.Offline, 1; got != want { + t.Fatalf("response.Summary.Offline = %d, want %d", got, want) + } + + if got, want := response.Summary.Online, 1; got != want { + t.Fatalf("response.Summary.Online = %d, want %d", got, want) + } } func TestHandleListLatestPlayerStatusesAppliesLimit(t *testing.T) {