perf: optimize JobsIndicator polling with visibility API and adaptive interval
Pause polling when the tab is hidden, refetch immediately when it becomes visible again, and use a 30s interval when no jobs are active instead of polling every 2s unconditionally. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -54,21 +54,46 @@ export function JobsIndicator() {
|
|||||||
const [popinStyle, setPopinStyle] = useState<React.CSSProperties>({});
|
const [popinStyle, setPopinStyle] = useState<React.CSSProperties>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let intervalId: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
const fetchActiveJobs = async () => {
|
const fetchActiveJobs = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/jobs/active");
|
const response = await fetch("/api/jobs/active");
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const jobs = await response.json();
|
const jobs: Job[] = await response.json();
|
||||||
setActiveJobs(jobs);
|
setActiveJobs(jobs);
|
||||||
|
// Adapt polling interval: 2s when jobs are active, 30s when idle
|
||||||
|
restartInterval(jobs.length > 0 ? 2000 : 30000);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch jobs:", error);
|
console.error("Failed to fetch jobs:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const restartInterval = (ms: number) => {
|
||||||
|
if (intervalId !== null) clearInterval(intervalId);
|
||||||
|
intervalId = setInterval(fetchActiveJobs, ms);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVisibilityChange = () => {
|
||||||
|
if (document.hidden) {
|
||||||
|
if (intervalId !== null) {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
intervalId = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Refetch immediately when tab becomes visible, then resume polling
|
||||||
|
fetchActiveJobs();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fetchActiveJobs();
|
fetchActiveJobs();
|
||||||
const interval = setInterval(fetchActiveJobs, 2000);
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||||
return () => clearInterval(interval);
|
|
||||||
|
return () => {
|
||||||
|
if (intervalId !== null) clearInterval(intervalId);
|
||||||
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Position the popin relative to the button
|
// Position the popin relative to the button
|
||||||
|
|||||||
Reference in New Issue
Block a user