From 9f85351b6b178b2007025a7ddadb5df11c848928 Mon Sep 17 00:00:00 2001 From: shats Date: Wed, 18 Feb 2026 12:02:29 +0700 Subject: [PATCH] refactor(NetworkMap): unify ping handling by implementing edge-based keying for ping timestamps in NetworkMapDashboard and NetworkMapUnifi components --- frontend/src/NetworkMapDashboard.jsx | 46 ++++++++++------------------ frontend/src/NetworkMapUnifi.jsx | 22 ++++--------- 2 files changed, 22 insertions(+), 46 deletions(-) diff --git a/frontend/src/NetworkMapDashboard.jsx b/frontend/src/NetworkMapDashboard.jsx index 9f71d64..74f9d45 100644 --- a/frontend/src/NetworkMapDashboard.jsx +++ b/frontend/src/NetworkMapDashboard.jsx @@ -139,11 +139,13 @@ export default function NetworkMapDashboard() { } }, []); + /** Один ключ пинга на ребро (маршруты статичны — одна сторона) */ + const edgePingKey = (a, b) => [String(a), String(b)].sort().join(':'); + const requestPings = useCallback(async () => { if (connections.length === 0) return; pingAbortRef.current = false; setPingLoading(true); - const key = (a, b) => `${a}:${b}`; const ttlMs = Math.max(0, (pingCacheSeconds || 0) * 1000); const tasks = []; @@ -158,26 +160,12 @@ export default function NetworkMapDashboard() { const canPingTo = srcTo && ['jumphost', 'home'].includes(String(srcTo.type || '').toLowerCase()) && c.internalToFrom; - // Проверка кеша: если TTL не истёк, не запускаем новый запрос - const keyFromTo = key(from, to); - const keyToFrom = key(to, from); - const now = Date.now(); - if (ttlMs > 0) { - const tsFrom = pingTimestampsRef.current[keyFromTo]; - if (tsFrom && now - tsFrom < ttlMs) { - // уже есть актуальное значение для from->to - } else if (!canPingFrom) { - // если пинговать нельзя, но кеша нет — оставляем как есть - } - const tsTo = pingTimestampsRef.current[keyToFrom]; - if (tsTo && now - tsTo < ttlMs) { - // уже есть актуальное значение для to->from - } else if (!canPingTo) { - // нельзя пинговать и кеша нет — пропускаем - } + const ekey = edgePingKey(from, to); + if (ttlMs > 0 && pingTimestampsRef.current[ekey] && Date.now() - pingTimestampsRef.current[ekey] < ttlMs) { + return; } - // Пингуем по ВНУТРЕННИМ адресам туннеля из /network-config + // Один пинг на ребро — с той стороны, где есть jumphost if (canPingFrom) { tasks.push(async () => { if (pingAbortRef.current) return; @@ -189,16 +177,14 @@ export default function NetworkMapDashboard() { count: 3, }); const ms = typeof data?.avgMs === 'number' ? Math.round(data.avgMs) : null; - pingTimestampsRef.current[keyFromTo] = Date.now(); - setPingMap((prev) => ({ ...prev, [keyFromTo]: ms })); + pingTimestampsRef.current[ekey] = Date.now(); + setPingMap((prev) => ({ ...prev, [ekey]: ms })); } catch { - pingTimestampsRef.current[keyFromTo] = Date.now(); - setPingMap((prev) => ({ ...prev, [keyFromTo]: null })); + pingTimestampsRef.current[ekey] = Date.now(); + setPingMap((prev) => ({ ...prev, [ekey]: null })); } }); - } - - if (canPingTo) { + } else if (canPingTo) { tasks.push(async () => { if (pingAbortRef.current) return; try { @@ -209,11 +195,11 @@ export default function NetworkMapDashboard() { count: 3, }); const ms = typeof data?.avgMs === 'number' ? Math.round(data.avgMs) : null; - pingTimestampsRef.current[keyToFrom] = Date.now(); - setPingMap((prev) => ({ ...prev, [keyToFrom]: ms })); + pingTimestampsRef.current[ekey] = Date.now(); + setPingMap((prev) => ({ ...prev, [ekey]: ms })); } catch { - pingTimestampsRef.current[keyToFrom] = Date.now(); - setPingMap((prev) => ({ ...prev, [keyToFrom]: null })); + pingTimestampsRef.current[ekey] = Date.now(); + setPingMap((prev) => ({ ...prev, [ekey]: null })); } }); } diff --git a/frontend/src/NetworkMapUnifi.jsx b/frontend/src/NetworkMapUnifi.jsx index b067a4a..9e30152 100644 --- a/frontend/src/NetworkMapUnifi.jsx +++ b/frontend/src/NetworkMapUnifi.jsx @@ -183,18 +183,16 @@ export default function NetworkMapUnifi({ servers = [], connections = [], pingMa [getSvgCoords, positions] ); + const edgePingKey = (a, b) => [String(a), String(b)].sort().join(':'); + const edgesWithPing = useMemo(() => { return (connections || []).map((c) => { const from = String(c.from); const to = String(c.to); const p1 = positions[from]; const p2 = positions[to]; - const fwd = pingMap[`${from}:${to}`]; - const rev = pingMap[`${to}:${from}`]; - const parts = []; - if (typeof fwd === 'number') parts.push(`→ ${fwd} ms`); - if (typeof rev === 'number') parts.push(`← ${rev} ms`); - const pingLabel = parts.length ? parts.join(' ') : null; + const ms = pingMap[edgePingKey(from, to)]; + const pingLabel = typeof ms === 'number' ? `${ms} ms` : null; const sk = speedKey(c.fromKey, c.toKey); const speed = speedMap[sk]; const speedLabel = @@ -435,8 +433,7 @@ export default function NetworkMapUnifi({ servers = [], connections = [], pingMa {selectedEdge && (() => { const fromServer = servers.find((s) => String(s.ip) === selectedEdge.from); const toServer = servers.find((s) => String(s.ip) === selectedEdge.to); - const fwd = pingMap[`${selectedEdge.from}:${selectedEdge.to}`]; - const rev = pingMap[`${selectedEdge.to}:${selectedEdge.from}`]; + const pingMs = pingMap[edgePingKey(selectedEdge.from, selectedEdge.to)]; const sk = speedKey(selectedEdge.raw?.fromKey, selectedEdge.raw?.toKey); const speed = speedMap[sk] ?? selectedEdge.speed; return ( @@ -520,14 +517,7 @@ export default function NetworkMapUnifi({ servers = [], connections = [], pingMa Пинг
-
- - {typeof fwd === 'number' ? `${fwd} ms` : 'нет данных'} -
-
- - {typeof rev === 'number' ? `${rev} ms` : 'нет данных'} -
+ {typeof pingMs === 'number' ? `${pingMs} ms` : 'нет данных'}
{speed && (speed.tcpDownloadBps != null || speed.tcpUploadBps != null) && (