fix(usage-stats): avoid partial stats on initial SSE race

Skip creating partial stats from SSE before the initial REST load
completes, keeping real-time merges limited to existing full stats.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weimaozhen
2026-06-13 10:23:56 +07:00
committed by decolua
parent b40e96d0ef
commit 564f2ece0d

View File

@@ -204,6 +204,7 @@ export default function UsageStats({ period: periodProp, setPeriod: setPeriodPro
const [providers, setProviders] = useState([]);
const [periodLocal, setPeriodLocal] = useState("today");
const isInitialLoad = useRef(true);
const hasLoadedStats = useRef(false);
const period = periodProp ?? periodLocal;
const setPeriod = setPeriodProp ?? setPeriodLocal;
@@ -242,14 +243,17 @@ export default function UsageStats({ period: periodProp, setPeriod: setPeriodPro
fetch(`/api/usage/stats?period=${period}`)
.then((r) => r.ok ? r.json() : null)
.then((data) => {
if (data) setStats((prev) => ({ ...prev, ...data }));
if (data) {
hasLoadedStats.current = true;
setStats((prev) => ({ ...prev, ...data }));
}
})
.catch(() => {})
.finally(() => {
setLoading(false);
setFetching(false);
});
}, [period]); // eslint-disable-line react-hooks/exhaustive-deps
}, [period]);
// SSE connection - real-time updates for activeRequests + recentRequests only
useEffect(() => {
@@ -259,14 +263,17 @@ export default function UsageStats({ period: periodProp, setPeriod: setPeriodPro
try {
const data = JSON.parse(e.data);
// Always merge only real-time fields, never overwrite full stats from REST
setStats((prev) => ({
...(prev || {}),
activeRequests: data.activeRequests,
recentRequests: data.recentRequests,
errorProvider: data.errorProvider,
pending: data.pending,
}));
setLoading(false);
setStats((prev) => {
if (!prev) return prev;
return {
...prev,
activeRequests: data.activeRequests,
recentRequests: data.recentRequests,
errorProvider: data.errorProvider,
pending: data.pending,
};
});
if (hasLoadedStats.current) setLoading(false);
} catch (err) {
console.error("[SSE CLIENT] parse error:", err);
}