-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseAdminActivity.ts
More file actions
68 lines (59 loc) · 2.18 KB
/
useAdminActivity.ts
File metadata and controls
68 lines (59 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import { useState, useEffect, useCallback, useRef } from "react";
import { adminWsClient } from "@/services/ws/adminClient";
import type {
ActivityStats,
ActivityChartResponse,
TopTalkgroupsResponse,
} from "@/app/slices/activitySlice";
const REFRESH_INTERVAL = 30_000;
const DEBOUNCE_MS = 3_000; // debounce rapid call bursts
export function useAdminActivity() {
const [stats, setStats] = useState<ActivityStats | null>(null);
const [chart, setChart] = useState<ActivityChartResponse | null>(null);
const [topTG, setTopTG] = useState<TopTalkgroupsResponse | null>(null);
const [isLoading, setIsLoading] = useState(true);
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const fetchAll = useCallback(async () => {
if (!adminWsClient.isConnected()) return;
try {
const [s, c, t] = await Promise.all([
adminWsClient.request<ActivityStats>("activity.stats"),
adminWsClient.request<ActivityChartResponse>("activity.chart"),
adminWsClient.request<TopTalkgroupsResponse>("activity.top-talkgroups"),
]);
setStats(s);
setChart(c);
setTopTG(t);
} catch {
// Silently fail - will retry on next interval
} finally {
setIsLoading(false);
}
}, []);
// Debounced fetch — coalesces rapid activity.updated bursts
const debouncedFetch = useCallback(() => {
if (debounceRef.current) clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(() => {
fetchAll();
}, DEBOUNCE_MS);
}, [fetchAll]);
useEffect(() => {
fetchAll();
const interval = setInterval(fetchAll, REFRESH_INTERVAL);
// Fetch immediately when WS (re)connects
const unsubConnect = adminWsClient.on("__connected__", () => {
fetchAll();
});
// Refresh when new calls arrive (debounced to avoid request storms)
const unsubActivity = adminWsClient.on("activity.updated", () => {
debouncedFetch();
});
return () => {
clearInterval(interval);
unsubConnect();
unsubActivity();
if (debounceRef.current) clearTimeout(debounceRef.current);
};
}, [fetchAll, debouncedFetch]);
return { stats, chart, topTG, isLoading, refetch: fetchAll };
}