Let a pinned minute read runs from the whole day

/observability/runs gains since/until, so the throughput chart's pin asks
the server for its minute instead of filtering a fixed recent list. This
engine writes ~60 runs a minute, so any minute but the newest read empty.

since is inclusive and until exclusive, matching the minute buckets the
charts are drawn from. Hover stays the client-side preview it was:
scrubbing a day would otherwise be a request per minute rested on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017MeiWk3Yq12n2pTvnQWYvt
This commit is contained in:
2026-08-17 00:27:40 +02:00
co-authored by Claude Fable 5
parent affb0a5f8c
commit 0b91379914
7 changed files with 94 additions and 12 deletions
@@ -17,6 +17,7 @@ import {
failuresQueryOptions,
healthKeys,
minuteOf,
minuteRunsQueryOptions,
runsQueryOptions,
timeseriesQueryOptions,
} from "./queries"
@@ -174,6 +175,7 @@ export function HealthActivity() {
const { data: series } = useQuery(timeseriesQueryOptions())
const { data: runs } = useQuery(runsQueryOptions())
const { data: pinnedRuns } = useQuery(minuteRunsQueryOptions(runsAt.pinned))
const { data: failures } = useQuery(failuresQueryOptions())
const { data: audit } = useQuery(auditQueryOptions())
const { data: dead } = useQuery(deadLetterQueryOptions())
@@ -201,10 +203,16 @@ export function HealthActivity() {
): HistoryPoint[] =>
points.map((point) => ({ ts: point.ts, value: pick(point) }))
// A pin is read back from the server, so it reaches a minute the recent list
// is nowhere near deep enough to hold. A hover stays the client-side preview
// it is: scrubbing a day's chart would otherwise be a request per minute the
// pointer rests on.
const shownRuns =
runsAt.at === null
? (runs ?? []).slice(0, RUNS_SHOWN)
: (runs ?? []).filter((run) => minuteOf(run.started_at) === runsAt.at)
runsAt.pinned !== null
? (pinnedRuns ?? [])
: runsAt.at === null
? (runs ?? []).slice(0, RUNS_SHOWN)
: (runs ?? []).filter((run) => minuteOf(run.started_at) === runsAt.at)
const shownFailures =
failuresAt.at === null
? (failures ?? []).slice(0, FAILURES_SHOWN)
@@ -282,7 +290,9 @@ export function HealthActivity() {
<p className="text-sm text-muted-foreground">
{runsAt.at === null
? "No runs recorded yet."
: "No run from this minute is in the recent list."}
: runsAt.pinned !== null
? "Nothing ran in this minute."
: "No run from this minute is in the recent list."}
</p>
)}
</div>
+23 -6
View File
@@ -9,13 +9,10 @@ const REFRESH = 30_000
/**
* How deep the run and failure lists are read.
*
* Deeper than they are shown: picking a minute off a chart filters these rows
* Deeper than they are shown: hovering a minute on a chart previews these rows
* client-side, and a list holding only the newest handful would have nothing
* to find for any minute but the current one.
*
* ponytail: the runs endpoint caps at 200 and takes no time range, so a busy
* engine still only covers its last minute or so. A `since` parameter is what
* would let a moment on the chart reach the whole day.
* to show for any minute but the current one. Pinning asks the server for the
* minute instead, which is what reaches past this depth.
*/
const RUN_DEPTH = 200
const EVENT_DEPTH = 100
@@ -53,6 +50,26 @@ export const runsQueryOptions = () => ({
refetchInterval: REFRESH,
})
/**
* The runs of one minute, wherever it sits in the day.
*
* A busy engine writes more runs per minute than the recent list is deep, so a
* pinned moment is asked for rather than filtered out of what is already held.
* `at` is a minute start, and the window is that minute.
*/
export const minuteRunsQueryOptions = (at: number | null) => ({
queryKey: ["observability", "runs", at] as const,
queryFn: () =>
ObservabilityService.readRuns({
since: new Date((at ?? 0) * 1000).toISOString(),
until: new Date(((at ?? 0) + 60) * 1000).toISOString(),
limit: RUN_DEPTH,
}),
// A minute that has passed does not change, and the current one is refreshed
// by the unpinned list anyway.
enabled: at !== null,
})
export const failuresQueryOptions = () => ({
queryKey: [...healthKeys.events, "failure"] as const,
queryFn: () =>