Count the runs in flight on Home, where an installation has any
Docs / docs (push) Successful in 25s
Playwright Tests / test-playwright (1, 2) (push) Successful in 3m13s
Playwright Tests / test-playwright (2, 2) (push) Successful in 1m50s
pre-commit / pre-commit (push) Failing after 2m6s
Test Backend / test-backend (push) Successful in 2m43s
Compose Smoke Test / test-compose (push) Successful in 31s
Playwright Tests / merge-reports (push) Successful in 1m16s

The tile only exists on an installation that has run something, which is the
same "nothing has been run yet" the Runs screen goes by. The count comes from
/runs/overview, already grouped by status in the database and already polled by
the Runs screen, so Home shares its cache entry rather than paging rows or
growing a second endpoint.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1moruzue2kTJd3uVisgNk
This commit is contained in:
2026-08-28 21:20:16 +02:00
co-authored by Claude Opus 5
parent 21caa354e7
commit 971bd430c7
2 changed files with 20 additions and 1 deletions
+2
View File
@@ -57,6 +57,8 @@ Always answers, degraded or not. The tiles cover:
- **Flows** — total, running, paused, quarantined, and how many cannot run
because their graph does not validate
- **Nodes** — how many failed to load
- **Runs running** — batch runs in flight right now, and how many are
waiting. Only on an installation that has run something
- **Queue** — depth, and how old the oldest pending item is
- **Loop lag** — whether the engine's event loop is keeping up
@@ -5,6 +5,7 @@ import type { FlowRollup, HistoryPoint } from "@/client"
import { type Range, RangePicker } from "@/components/Common/RangePicker"
import { Sparkline } from "@/components/Common/Sparkline"
import { PANEL_SECTION } from "@/components/Flow/SidePanel"
import { runOverviewQueryOptions } from "@/components/Runs/queries"
import { Badge } from "@/components/ui/badge"
import { dur, si } from "@/lib/utils"
import {
@@ -82,10 +83,17 @@ export function HealthOverview({
const { data: flows } = useQuery(flowRollupsQueryOptions(range))
// Shares the list below's cache entry, for the one tile that dates them.
const { data: failures } = useQuery(failuresQueryOptions(range))
// Shares the Runs screen's cache entry, which already counts by status in
// the database rather than over a page of rows.
const { data: runs } = useQuery(runOverviewQueryOptions())
const queue = (summary?.queue ?? {}) as Record<string, number>
const degraded = summary?.status === "degraded"
const errors = (flows ?? []).reduce((total, row) => total + row.errors, 0)
// An installation nobody has run a batch flow on has no runs tile at all —
// the same "nothing has been run yet" the Runs screen itself goes by.
const running = (runs ?? []).reduce((total, row) => total + row.running, 0)
const queued = (runs ?? []).reduce((total, row) => total + row.queued, 0)
return (
<>
@@ -105,7 +113,9 @@ export function HealthOverview({
</p>
) : null}
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
<div
className={`grid gap-3 sm:grid-cols-2 ${runs?.length ? "lg:grid-cols-6" : "lg:grid-cols-5"}`}
>
<Tile
label="Nodes"
value={String(summary?.nodes.total ?? 0)}
@@ -132,6 +142,13 @@ export function HealthOverview({
.join(" · ") || "none paused"
}
/>
{runs?.length ? (
<Tile
label="Runs running"
value={String(running)}
note={queued ? `${queued} queued` : "none queued"}
/>
) : null}
<Tile
label={`Failures (${range.label})`}
// Summed from the rollups the table below is drawn from, so the