fix(beszel): address review findings for live streaming
- Skip toReversed() for live data (already chronological from buffer) - Reset live buffer on systemId/integration change to avoid stale data - Throw on unexpected SSE stream end so subscription emits error - Delete unused time-period.ts config (duplicate of server-side config)
This commit is contained in:
4 files changed
+19
-23
No files matched your search
@@ -329,6 +329,9 @@ export class BeszelIntegration extends Integration {
|
||||
processLine(line);
|
||||
}
|
||||
}
|
||||
if (!signal.aborted) {
|
||||
throw new Error("Beszel SSE stream ended unexpectedly");
|
||||
}
|
||||
} finally {
|
||||
reader.cancel().catch(() => {});
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ export const useSystemChartData = (
|
||||
useMemo(() => {
|
||||
if (!systemStats) return [];
|
||||
const fmt = live ? formatTimeLive : formatTime;
|
||||
return [...systemStats].toReversed().map((r) => ({
|
||||
const ordered = live ? systemStats : [...systemStats].toReversed();
|
||||
return ordered.map((r) => ({
|
||||
time: fmt(r.created),
|
||||
...mapFn(r.stats),
|
||||
}));
|
||||
@@ -123,7 +124,8 @@ export const useDockerChartData = (
|
||||
const extract = defaultContainerExtractors[metric];
|
||||
if (!extract) return [];
|
||||
const fmt = live ? formatTimeLive : formatTime;
|
||||
return [...containerStats].toReversed().map((record) => {
|
||||
const ordered = live ? containerStats : [...containerStats].toReversed();
|
||||
return ordered.map((record) => {
|
||||
const point: Record<string, unknown> = { time: fmt(record.created) };
|
||||
for (const name of containerNames) {
|
||||
point[name] = extract(record.stats.find((c) => c.n === name));
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
export const beszelTimePeriods = ["1m", "1h", "12h", "24h", "1w", "30d"] as const;
|
||||
export type BeszelTimePeriod = (typeof beszelTimePeriods)[number];
|
||||
|
||||
export const beszelTimePeriodConfig: Record<
|
||||
BeszelTimePeriod,
|
||||
{
|
||||
beszelStatType: string;
|
||||
perPage: number;
|
||||
refetchMs: number;
|
||||
serverCacheSeconds: number;
|
||||
}
|
||||
> = {
|
||||
"1m": { beszelStatType: "1m", perPage: 60, refetchMs: 0, serverCacheSeconds: 5 },
|
||||
"1h": { beszelStatType: "1m", perPage: 60, refetchMs: 60_000, serverCacheSeconds: 60 },
|
||||
"12h": { beszelStatType: "10m", perPage: 72, refetchMs: 300_000, serverCacheSeconds: 300 },
|
||||
"24h": { beszelStatType: "20m", perPage: 72, refetchMs: 600_000, serverCacheSeconds: 600 },
|
||||
"1w": { beszelStatType: "120m", perPage: 84, refetchMs: 1_800_000, serverCacheSeconds: 1800 },
|
||||
"30d": { beszelStatType: "480m", perPage: 90, refetchMs: 3_600_000, serverCacheSeconds: 3600 },
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import type { BeszelContainerStatsRecord, BeszelSystemStatsRecord } from "@homarr/integrations/types";
|
||||
@@ -12,10 +12,20 @@ interface LiveStatsData {
|
||||
containerStats: BeszelContainerStatsRecord[];
|
||||
}
|
||||
|
||||
export const useLiveStats = (integrationIds: string[], systemId: string, includeDocker: boolean, enabled: boolean) => {
|
||||
export const useLiveStats = (
|
||||
integrationIds: string[],
|
||||
systemId: string,
|
||||
includeDocker: boolean,
|
||||
enabled: boolean,
|
||||
) => {
|
||||
const bufferRef = useRef<LiveStatsData>({ systemStats: [], containerStats: [] });
|
||||
const [data, setData] = useState<LiveStatsData | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
bufferRef.current = { systemStats: [], containerStats: [] };
|
||||
setData(null);
|
||||
}, [systemId, enabled, ...integrationIds]);
|
||||
|
||||
const onData = useCallback(
|
||||
(incoming: { stats: BeszelSystemStatsRecord; containerStats: BeszelContainerStatsRecord | null }) => {
|
||||
const buf = bufferRef.current;
|
||||
|
||||
Reference in new issue
Block a user