diff --git a/src/components/fleet/event-log.tsx b/src/components/fleet/event-log.tsx index b225e06..b8fa89b 100644 --- a/src/components/fleet/event-log.tsx +++ b/src/components/fleet/event-log.tsx @@ -32,10 +32,11 @@ function formatTime(date: Date | string): string { export function EventLog({ nodeId, range }: EventLogProps) { const trpc = useTRPC(); - const { data: events, isLoading } = useQuery({ + const { data, isLoading } = useQuery({ ...trpc.fleet.getStatusTimeline.queryOptions({ nodeId, range }), refetchInterval: 15_000, }); + const events = data?.events; if (isLoading) { return ( diff --git a/src/components/fleet/status-timeline.tsx b/src/components/fleet/status-timeline.tsx index 565b823..51a3d8b 100644 --- a/src/components/fleet/status-timeline.tsx +++ b/src/components/fleet/status-timeline.tsx @@ -55,10 +55,12 @@ function formatDuration(ms: number): string { export function StatusTimeline({ nodeId, range, onRangeChange }: StatusTimelineProps) { const trpc = useTRPC(); - const { data: events, isLoading, dataUpdatedAt } = useQuery({ + const { data, isLoading, dataUpdatedAt } = useQuery({ ...trpc.fleet.getStatusTimeline.queryOptions({ nodeId, range }), refetchInterval: 15_000, }); + const events = data?.events; + const nodeStatus = data?.nodeStatus ?? "UNKNOWN"; type Segment = { status: string; @@ -82,7 +84,7 @@ export function StatusTimeline({ nodeId, range, onRangeChange }: StatusTimelineP if (events !== undefined && now > 0) { if (events.length === 0) { - segs.push({ status: "UNKNOWN", start: rangeStart, end: now }); + segs.push({ status: nodeStatus, start: rangeStart, end: now }); } else { // First segment: from range start to first event const firstStatus = events[0].fromStatus ?? "UNKNOWN"; @@ -98,7 +100,7 @@ export function StatusTimeline({ nodeId, range, onRangeChange }: StatusTimelineP } return { segments: segs, totalMs: now - rangeStart }; - }, [events, range, dataUpdatedAt]); + }, [events, nodeStatus, range, dataUpdatedAt]); return (
diff --git a/src/server/routers/fleet.ts b/src/server/routers/fleet.ts index 10ce782..bc882c3 100644 --- a/src/server/routers/fleet.ts +++ b/src/server/routers/fleet.ts @@ -72,10 +72,17 @@ export const fleetRouter = router({ "30d": 30 * 24 * 60 * 60 * 1000, }; const since = new Date(Date.now() - rangeMs[input.range]); - return prisma.nodeStatusEvent.findMany({ - where: { nodeId: input.nodeId, timestamp: { gte: since } }, - orderBy: { timestamp: "asc" }, - }); + const [events, node] = await Promise.all([ + prisma.nodeStatusEvent.findMany({ + where: { nodeId: input.nodeId, timestamp: { gte: since } }, + orderBy: { timestamp: "asc" }, + }), + prisma.vectorNode.findUnique({ + where: { id: input.nodeId }, + select: { status: true }, + }), + ]); + return { events, nodeStatus: node?.status ?? "UNKNOWN" }; }), getUptime: protectedProcedure @@ -100,16 +107,23 @@ export const fleetRouter = router({ orderBy: { timestamp: "asc" }, }); - // Get the last event before the range to know starting status - const priorEvent = await prisma.nodeStatusEvent.findFirst({ - where: { nodeId: input.nodeId, timestamp: { lt: since } }, - orderBy: { timestamp: "desc" }, - }); + // Get the last event before the range to know starting status, + // and the node's current status as a fallback for nodes with no event history + const [priorEvent, nodeForStatus] = await Promise.all([ + prisma.nodeStatusEvent.findFirst({ + where: { nodeId: input.nodeId, timestamp: { lt: since } }, + orderBy: { timestamp: "desc" }, + }), + prisma.vectorNode.findUnique({ + where: { id: input.nodeId }, + select: { status: true }, + }), + ]); // Walk events, tracking time in HEALTHY status let healthySeconds = 0; let incidents = 0; - let currentStatus = priorEvent?.toStatus ?? "UNKNOWN"; + let currentStatus = priorEvent?.toStatus ?? nodeForStatus?.status ?? "UNKNOWN"; let cursor = since.getTime(); for (const event of events) {