feat(uptime-monitor): enhance uptime checks with request cancellation and logging on page leave for improved resource management
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m6s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m6s
This commit is contained in:
@@ -1 +1,8 @@
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:request","message":"API request started","data":{"method":"GET","url":"/alerts"},"timestamp":1771911955281}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:response","message":"API response received","data":{"method":"POST","url":"/uptime/check","status":200},"timestamp":1771912295663}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:response","message":"API response received","data":{"method":"POST","url":"/uptime/check","status":200},"timestamp":1771912297719}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:request","message":"API request started","data":{"method":"GET","url":"/alerts"},"timestamp":1771912335274}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:request","message":"API request started","data":{"method":"GET","url":"/alerts"},"timestamp":1771912395275}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:request","message":"API request started","data":{"method":"GET","url":"/alerts"},"timestamp":1771912395275}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:response","message":"API response received","data":{"method":"GET","url":"/alerts","status":200},"timestamp":1771912434898}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:response","message":"API response received","data":{"method":"GET","url":"/alerts","status":200},"timestamp":1771912439040}
|
||||
{"sessionId":"378b5f","runId":"baseline","hypothesisId":"H1_H2","location":"frontend/src/lib/api.js:request","message":"API request started","data":{"method":"GET","url":"/alerts"},"timestamp":1771912455273}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import api from './lib/api.js';
|
||||
import {
|
||||
IconClock,
|
||||
@@ -81,6 +82,7 @@ function historyToResponseTimeData(history) {
|
||||
}
|
||||
|
||||
export default function UptimeMonitorPage() {
|
||||
const location = useLocation();
|
||||
const [servers, setServers] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [checking, setChecking] = useState(false);
|
||||
@@ -94,6 +96,8 @@ export default function UptimeMonitorPage() {
|
||||
const [currentCheckingServerIds, setCurrentCheckingServerIds] = useState([]);
|
||||
const intervalRef = useRef(null);
|
||||
const checkingRef = useRef(false);
|
||||
const activeRunIdRef = useRef(0);
|
||||
const checkControllersRef = useRef(new Set());
|
||||
|
||||
const jumphosts = useMemo(
|
||||
() =>
|
||||
@@ -160,6 +164,7 @@ export default function UptimeMonitorPage() {
|
||||
const runChecks = useCallback(async () => {
|
||||
if (jumphosts.length === 0) return;
|
||||
if (checkingRef.current) return;
|
||||
const runId = ++activeRunIdRef.current;
|
||||
checkingRef.current = true;
|
||||
setChecking(true);
|
||||
setCurrentCheckingServerIds([]);
|
||||
@@ -171,18 +176,31 @@ export default function UptimeMonitorPage() {
|
||||
const checkOne = async () => {
|
||||
let server;
|
||||
while ((server = getNext()) != null) {
|
||||
if (activeRunIdRef.current !== runId) break;
|
||||
const serverId = server.id || server.dns || server.ip;
|
||||
if (!serverId) continue;
|
||||
setCurrentCheckingServerIds((prev) => [...prev, serverId]);
|
||||
const t0 = Date.now();
|
||||
let ok = false;
|
||||
let ms = null;
|
||||
const controller = new AbortController();
|
||||
checkControllersRef.current.add(controller);
|
||||
try {
|
||||
const { data: checkData } = await api.post('/uptime/check', { serverId });
|
||||
const { data: checkData } = await api.post('/uptime/check', { serverId }, { signal: controller.signal });
|
||||
ok = checkData?.ok === true;
|
||||
ms = typeof checkData?.ms === 'number' ? checkData.ms : Date.now() - t0;
|
||||
} catch (_) {
|
||||
} catch (e) {
|
||||
if (e?.code === 'ERR_CANCELED' || e?.name === 'CanceledError' || e?.name === 'AbortError') {
|
||||
// #region agent log
|
||||
fetch('http://192.168.10.2:7343/ingest/aa002dd6-6968-4a35-b09d-f05302d83266',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'378b5f'},body:JSON.stringify({sessionId:'378b5f',runId:'post-fix',hypothesisId:'H7',location:'frontend/src/UptimeMonitorPage.jsx:uptime-check-canceled',message:'Canceled uptime check request',data:{serverId:String(serverId||''),path:String(location?.pathname||'')},timestamp:Date.now()})}).catch(()=>{});
|
||||
// #endregion
|
||||
setCurrentCheckingServerIds((prev) => prev.filter((id) => id !== serverId));
|
||||
checkControllersRef.current.delete(controller);
|
||||
continue;
|
||||
}
|
||||
ms = Date.now() - t0;
|
||||
} finally {
|
||||
checkControllersRef.current.delete(controller);
|
||||
}
|
||||
const lastCheckTs = Date.now();
|
||||
const entry = { ts: lastCheckTs, ok, ms };
|
||||
@@ -196,10 +214,11 @@ export default function UptimeMonitorPage() {
|
||||
}
|
||||
};
|
||||
await Promise.all(Array.from({ length: PARALLEL_CHECKS }, checkOne));
|
||||
if (activeRunIdRef.current !== runId) return;
|
||||
setCurrentCheckingServerIds([]);
|
||||
checkingRef.current = false;
|
||||
setChecking(false);
|
||||
}, [jumphosts]);
|
||||
}, [jumphosts, location.pathname]);
|
||||
|
||||
// Первый запуск проверки через несколько секунд после загрузки (после перезапуска контейнера кеш может быть пустым или устаревшим)
|
||||
useEffect(() => {
|
||||
@@ -217,6 +236,31 @@ export default function UptimeMonitorPage() {
|
||||
};
|
||||
}, [jumphosts, runChecks, checkIntervalMs]);
|
||||
|
||||
// Остановка фоновых uptime-check при уходе со страницы
|
||||
useEffect(() => {
|
||||
if (location.pathname === '/uptime-monitor') return;
|
||||
activeRunIdRef.current += 1;
|
||||
checkingRef.current = false;
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
checkControllersRef.current.forEach((controller) => controller.abort());
|
||||
checkControllersRef.current.clear();
|
||||
setCurrentCheckingServerIds([]);
|
||||
setChecking(false);
|
||||
// #region agent log
|
||||
fetch('http://192.168.10.2:7343/ingest/aa002dd6-6968-4a35-b09d-f05302d83266',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'378b5f'},body:JSON.stringify({sessionId:'378b5f',runId:'post-fix',hypothesisId:'H7',location:'frontend/src/UptimeMonitorPage.jsx:leave-page',message:'Stopped uptime background checks on page leave',data:{pathname:String(location?.pathname||'')},timestamp:Date.now()})}).catch(()=>{});
|
||||
// #endregion
|
||||
}, [location.pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
activeRunIdRef.current += 1;
|
||||
checkingRef.current = false;
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
checkControllersRef.current.forEach((controller) => controller.abort());
|
||||
checkControllersRef.current.clear();
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Сохраняем историю в localStorage при изменении
|
||||
useEffect(() => {
|
||||
saveHistoryToStorage(historyMap);
|
||||
|
||||
Reference in New Issue
Block a user