Skip to content

feat(dashboard): Eingangs-Status „Simulation (intern)" an Live-Stream koppeln - #49

Merged
patricznr1 merged 3 commits into
mainfrom
feat/sim-eingangs-status
Jun 25, 2026
Merged

feat(dashboard): Eingangs-Status „Simulation (intern)" an Live-Stream koppeln#49
patricznr1 merged 3 commits into
mainfrom
feat/sim-eingangs-status

Conversation

@patricznr1

@patricznr1 patricznr1 commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Ziel

Die Plattform-Topologie-Kachel „Simulation (intern)" und das globale „Live"-Badge spiegeln jetzt denselben datengetriebenen Zustand des Eingangs-Live-Streams (digitaler Zwilling als Datenquelle) — statt eines Etiketts ohne Substanz.

Befund (korrigiert die Auftrags-Prämisse)

Der Status der Kachel war nicht statischer Text: topology/service.py:_source_nodes leitet ihn längst aus max(Reading.time) der simulation-Quelle ab. Das eigentliche Etikett-ohne-Substanz war das „Live"-Badge — es hing am WS-Transport-Zustand, nicht am Stream, und hätte „Live" über rein statischer Historie gezeigt. Diese PR schließt den echten Riss.

Änderungen

Backend

  • reads/stream.py (neu): build_stream_status / classify_stream → aktiv/inaktiv aus dem jüngsten simulation-Reading gegen STREAM_FRESH_WINDOW (5 min, kalibriert auf den 60-s-Worker-Takt). Die eine Wahrheit für Kachel UND Badge.
  • GET /api/v1/overview (FleetOverviewOut) trägt stream: {active, last_reading_at} — über build_fleet_overview, also HTTP und WS-Push zugleich, scope-unabhängig.
  • topology/service.py: die interne simulation-Quelle wird gegen dasselbe enge Stream-Fenster gemessen wie das Badge (Konsistenz); externe Protokolle behalten das generische fresh_within_minutes.

Frontend

  • global-status-bar: „Live" nur bei offener WS-Verbindung und tickendem Stream; sonst „Verlauf" (ProvenanceStamp um history erweitert). Logik als reine Funktion streamBadgeFreshness.
  • Topologie-Kachel rendert für die interne Quelle „aktiv" statt „verbunden" (connectionStatusLabel) — Backend-Statusvertrag bleibt stabil, nur die UI-Sprache wird ehrlicher.

Konsistenz & Verfassung

  • Kachel und Badge messen denselben last_reading_at gegen dieselbe Schwelle → spiegeln dieselbe Wahrheit. „aktiv"/„Live" nur, wenn der Worker wirklich tickt.
  • Die Eingangs-Simulation (Zwilling) ist die Quelle; FOREMANs internes Reasoning-Simulieren (F-LLM: Modell-Gateway — LLMGateway-Abstraktion über LiteLLM #5) taucht hier nicht als aktive Quelle auf.

Bewusste Design-Entscheidung (server-autoritativ)

Reine Reading-Ticks lösen kein overview-Reload aus (topics_for_change: Readings → nur trend). Den Ingest-NOTIFY-Kern dafür anzufassen wäre ein schwerer F3/F5-Eingriff außerhalb des „schlanken" Auftrags. Daher ist stream.active server-autoritativ zum overview-Load (Seiten-Load / Alarm-Event / Reconnect) — korrekt und ehrlich, ohne clientseitige Alterung, die bei laufendem Worker lügen würde. Ein Stopp wird beim nächsten overview-Load erkannt; die 5-min-Schwelle deckt die typische Latenz.

Abnahme

  • ✅ Status flippt auf Stream-Start/-Stopp (kein statischer Text) — test_topology.py (Stream-Fenster), test_reads_stream.py, test_reads_overview.py.
  • ✅ „Live"-Badge konsistent — global-status-bar.test.tsx (Verlauf bei inaktivem Stream, Live bei tickendem), stream-freshness.test.ts.
  • ✅ Anzeige stimmt mit DB-Realität überein (aus max(Reading.time)).

Gates (lokal grün)

ruff 0 · mypy --strict 0 · pytest 859 passed @ 94.31 % · tsc 0 · ESLint 0 · vitest 656 passed. GROUND_TRUTH §4 / §20.1 / §22.2 im selben Commit nachgezogen.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Neue Funktionen
    • Die Flotten-Übersicht zeigt jetzt zusätzlich den Status des Eingangs-Streams inkl. „aktiv“/„Verlauf“ und Zeitstempel des letzten Empfangs.
    • Live-/Provenance- und Statusanzeigen unterscheiden nun konsistent zwischen „Live“, „Verlauf“ und „Gecacht“ sowie bei internen Quellen zwischen „aktiv“ und „verbunden“.
  • Bug Fixes
    • Die Anzeige basiert für interne Simulationen auf einem realistischen Stream-Fenster und ist dadurch ehrlicher zwischen Live und statischer Historie.
  • Tests
    • Zusätzliche Unit- und Integrationsabdeckung für Stream-Freshness, Edge-Fälle sowie Serialisierung des Stream-Status.

… koppeln

Die Plattform-Topologie-Kachel „Simulation (intern)" und das globale
„Live"-Badge spiegeln jetzt denselben datengetriebenen Zustand des
Eingangs-Live-Streams (Zwilling als Datenquelle) statt eines Transport-
Etiketts.

- reads/stream.py (NEU): build_stream_status/classify_stream — aktiv/inaktiv
  aus dem jüngsten simulation-Reading gegen STREAM_FRESH_WINDOW (5 min),
  die EINE Wahrheit für Kachel UND Badge.
- /overview (FleetOverviewOut) trägt stream:{active,last_reading_at}
  (HTTP + WS-Push, scope-unabhängig).
- Live-Badge (global-status-bar): „Live" nur bei offener WS UND tickendem
  Stream; sonst „Verlauf" — kein Live-Etikett über statischer Historie.
- Topologie-Kachel: interne Quelle gegen das enge Stream-Fenster gemessen
  (konsistent mit dem Badge); FE rendert „aktiv" statt „verbunden"
  (Backend-Statusvertrag stabil).
- Verfassung: ehrlicher Zustand, „aktiv" nur wenn wirklich getickt wird.
  FOREMANs internes Reasoning-Simulieren (#5) bleibt außen vor.

Gates grün: ruff/mypy --strict 0, pytest 859 passed @94.31%, tsc 0,
ESLint 0, vitest 656 passed. GROUND_TRUTH §4/§20.1/§22.2 nachgezogen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e3cb8fe4-3b4d-421a-906d-b74271baeb8a

📥 Commits

Reviewing files that changed from the base of the PR and between 4cac5d7 and 3e7bfda.

📒 Files selected for processing (1)
  • src/foreman/reads/stream.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/foreman/reads/stream.py

📝 Walkthrough

Walkthrough

Der PR ergänzt einen zentralen Stream-Status im Read-Core, erweitert den Overview-/Dashboard-Vertrag um stream, passt Badge- und Provenance-Anzeigen an und unterscheidet interne Simulationen in der Topologie über aktiv statt verbunden.

Changes

Stream-Status und Anzeige

Layer / File(s) Summary
Stream-Status im Read-Core
GROUND_TRUTH.md, src/foreman/reads/stream.py, src/foreman/reads/overview.py, tests/unit/test_reads_stream.py, tests/integration/test_reads_stream.py, tests/integration/test_reads_overview.py
build_stream_status ermittelt StreamStatus aus simulation-Readings, build_fleet_overview hängt ihn an FleetOverview, und die Stream-/Overview-Tests prüfen Aktivität sowie last_reading_at.
Dashboard-Contract und Overview
GROUND_TRUTH.md, src/foreman/schemas/dashboard.py, frontend/lib/api/contracts.ts, tests/unit/test_dashboard_schemas.py, frontend/components/alarms/alarms-view.test.tsx, frontend/components/cockpit/cockpit-view.test.tsx, frontend/lib/alarms/counts.test.ts
FleetOverviewOut und StreamStatusOut tragen stream, und die zugehörigen Serialisierungs- und Fixture-Tests übernehmen active und last_reading_at.
Live-Badge-Frische
frontend/lib/ui/stream-freshness.ts, frontend/lib/ui/stream-freshness.test.ts, frontend/components/atoms/provenance-stamp.tsx, frontend/components/atoms/atoms.test.tsx, frontend/components/shell/global-status-bar.tsx, frontend/components/shell/global-status-bar.test.tsx
Die Frische-Hilfsfunktion unterscheidet live, cached und history; ProvenanceStamp zeigt Verlauf, und GlobalStatusBar stempelt den Badge-Zustand mit overview.stream.last_reading_at.
Topologie und interne Quelle
GROUND_TRUTH.md, src/foreman/topology/service.py, tests/topology/test_topology.py, frontend/lib/platform/status.ts, frontend/lib/platform/status.test.ts, frontend/components/platform/topology-graph.tsx, frontend/components/platform/topology-node-mark.tsx, frontend/components/platform/topology-graph.test.tsx
Die Topologie nutzt für SIM_SOURCE das enge Stream-Fenster, connectionStatusLabel rendert internes verbunden als aktiv, und die Topologie-Tests zeigen diese Unterscheidung.

Sequence Diagram(s)

sequenceDiagram
  participant build_fleet_overview
  participant build_stream_status
  participant latest_source_reading
  participant AsyncSession

  build_fleet_overview->>build_stream_status: stream status anfordern
  build_stream_status->>latest_source_reading: source="simulation"
  latest_source_reading->>AsyncSession: SELECT max(Reading.time) via DataPoint.source
  AsyncSession-->>latest_source_reading: last_reading_at
  latest_source_reading-->>build_stream_status: last_reading_at
  build_stream_status->>build_stream_status: classify_stream(...)
  build_stream_status-->>build_fleet_overview: StreamStatus{active,last_reading_at}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • patricznr1/foreman#18: Erweiterte denselben Overview-/Stream-Contract rund um build_fleet_overview und stream.
  • patricznr1/foreman#32: Behandelt dieselbe Topologie-/Statusableitung für simulation-Quellen; der aktuelle PR richtet diese Logik zusätzlich auf den neuen Stream-Status aus.

Poem

Ich hüpfe durch den Stream, ganz munter,
mal „Live“, mal „Verlauf“, mal „Gecacht“ darunter.
Für simulation gilt das kleine Fenster fein,
und in der Topologie sagt’s ehrlich: „aktiv“ sein.
🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.95% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Der Titel beschreibt die zentrale Änderung treffend: den internen Simulations-Eingangsstatus an den Live-Stream koppeln.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sim-eingangs-status

Comment @coderabbitai help to get the list of available commands.

Regression-Guard (Review-Befund): beweist, dass der jüngste Reading-Stempel
ÜBER ALLE simulation-Datenpunkte den Stream-Stand bestimmt (Aggregat-Semantik),
nicht ein beliebiger/erster Datenpunkt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/foreman/reads/stream.py`:
- Around line 63-66: The formatting in the read freshness check is not aligned
with ruff format, so update the multi-line conditional expression in the
stream-reading helper to match the formatter’s output. Reformat the stamp
assignment and return logic in the function that compares last_reading_at
against fresh_window so it follows the exact style produced by uv run ruff
format src/foreman/reads/stream.py, preserving behavior while matching CI
formatting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 02474b1d-df39-4067-9e93-a6166cd9eedc

📥 Commits

Reviewing files that changed from the base of the PR and between 978523f and 4cac5d7.

📒 Files selected for processing (25)
  • GROUND_TRUTH.md
  • frontend/components/alarms/alarms-view.test.tsx
  • frontend/components/atoms/atoms.test.tsx
  • frontend/components/atoms/provenance-stamp.tsx
  • frontend/components/cockpit/cockpit-view.test.tsx
  • frontend/components/platform/topology-graph.test.tsx
  • frontend/components/platform/topology-graph.tsx
  • frontend/components/platform/topology-node-mark.tsx
  • frontend/components/shell/global-status-bar.test.tsx
  • frontend/components/shell/global-status-bar.tsx
  • frontend/lib/alarms/counts.test.ts
  • frontend/lib/api/contracts.ts
  • frontend/lib/platform/status.test.ts
  • frontend/lib/platform/status.ts
  • frontend/lib/ui/stream-freshness.test.ts
  • frontend/lib/ui/stream-freshness.ts
  • src/foreman/reads/overview.py
  • src/foreman/reads/stream.py
  • src/foreman/schemas/dashboard.py
  • src/foreman/topology/service.py
  • tests/integration/test_reads_overview.py
  • tests/integration/test_reads_stream.py
  • tests/topology/test_topology.py
  • tests/unit/test_dashboard_schemas.py
  • tests/unit/test_reads_stream.py

Comment thread src/foreman/reads/stream.py Outdated
CI-Fix: ruff format --check verlangt die geklammerte Mehrzeilen-Form des
ternären Ausdrucks. Verhaltensneutral.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@patricznr1
patricznr1 merged commit 0c8c71f into main Jun 25, 2026
3 checks passed
@patricznr1
patricznr1 deleted the feat/sim-eingangs-status branch June 25, 2026 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant