fix(ui): проверять источник IPv4 для диагностики
This commit is contained in:
1 parent
d0c715e93c
commit
b60b7ac8e8
8 files changed
+81
-26
No files matched your search
+28
-22
@@ -2,6 +2,7 @@
|
||||
|
||||
import { Suspense, useEffect, useRef, useState, useMemo, useCallback } from "react"
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import { readProbeSource } from "@/lib/probe-source"
|
||||
import { readProbeUrl, patchProbeUrl } from "@/lib/probe-url"
|
||||
import { PageHeader } from "@/components/page-header"
|
||||
import { FormToggle } from "@/components/form-kit"
|
||||
@@ -616,7 +617,8 @@ function ProbesContent() {
|
||||
const [bwDuration, setBwDuration] = useState(10)
|
||||
const [runBusy, setRunBusy] = useState(false)
|
||||
/** В live: IPv4 для src-address (DNS A-запись к host API); undefined = грузим, null = не удалось */
|
||||
const [rosSrcV4, setRosSrcV4] = useState<string | null | undefined>(undefined)
|
||||
const [source, setSource] = useState<{ key: string; ipv4?: string | null; error?: string; loading: boolean } | null>(null)
|
||||
const [sourceRevision, setSourceRevision] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLive || !canRead) return
|
||||
@@ -664,27 +666,6 @@ function ProbesContent() {
|
||||
}))
|
||||
), [allServers])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLive || !canRead || liveLoad !== "idle" || !allServers.some(s => s.id === srcId && s.enabled)) {
|
||||
queueMicrotask(() => setRosSrcV4(undefined))
|
||||
return
|
||||
}
|
||||
const n = Number.parseInt(srcId, 10)
|
||||
if (!Number.isFinite(n)) {
|
||||
setRosSrcV4(undefined)
|
||||
return
|
||||
}
|
||||
let cancelled = false
|
||||
setRosSrcV4(undefined)
|
||||
void apiFetch<{ ipv4: string | null }>(`/api/servers/${n}/ros-src-address`)
|
||||
.then((r) => {
|
||||
if (!cancelled) setRosSrcV4(r.ipv4)
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setRosSrcV4(null)
|
||||
})
|
||||
return () => { cancelled = true }
|
||||
}, [isLive, canRead, liveLoad, allServers, srcId, apiFetch])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLive || !canReadGre || liveLoad !== "idle" || !allServers.some(s => s.id === srcId && s.enabled)) return
|
||||
@@ -735,6 +716,22 @@ function ProbesContent() {
|
||||
|
||||
const bwTunnels = tunnelsForSrc
|
||||
const srcServer = useMemo(() => allServers.find(s => s.id === srcId), [allServers, srcId])
|
||||
const sourceKey = JSON.stringify([srcId, srcServer?.host])
|
||||
const sourceRequired = tool === "ping" || tool === "traceroute" || tool === "mtu"
|
||||
const sourceCurrent = source?.key === sourceKey ? source : null
|
||||
const rosSrcV4 = sourceCurrent?.ipv4
|
||||
useEffect(() => {
|
||||
if (!isLive || !canRead || liveLoad !== "idle" || !srcServer?.enabled || !sourceRequired) return
|
||||
const host = srcServer.host, id = srcServer.id
|
||||
if (!/^[1-9][0-9]*$/.test(id) || !Number.isSafeInteger(Number(id))) return
|
||||
let cancelled = false
|
||||
const ctrl = new AbortController()
|
||||
queueMicrotask(() => { if (!cancelled) setSource({ key: sourceKey, loading: true }) })
|
||||
void apiFetch<unknown>("/api/servers/" + id + "/ros-src-address", { signal: ctrl.signal })
|
||||
.then(raw => { const ipv4 = readProbeSource(raw, host); if (!cancelled) setSource({ key: sourceKey, loading: false, ipv4 }) })
|
||||
.catch(error => { if (!cancelled) setSource({ key: sourceKey, loading: false, error: error instanceof Error ? error.message : "Источник preview неизвестен." }) })
|
||||
return () => { cancelled = true; ctrl.abort() }
|
||||
}, [isLive, canRead, liveLoad, srcServer, sourceRequired, sourceKey, apiFetch, sourceRevision])
|
||||
const greReady = !isLive || (greState?.id === srcId && greState.state === "ready")
|
||||
const bwTun = useMemo(() => bwTunnels.find(t => t.id === bwTunId), [bwTunnels, bwTunId])
|
||||
|
||||
@@ -1000,6 +997,15 @@ function ProbesContent() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isLive && srcServer?.enabled && sourceRequired && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{sourceCurrent?.error ? <div role="alert" aria-label="Источник preview"><p>{sourceCurrent.error}</p><Button type="button" size="sm" variant="outline" onClick={() => setSourceRevision(n => n + 1)}>Повторить определение IPv4</Button></div>
|
||||
: !sourceCurrent || sourceCurrent.loading ? <p role="status">Определяем IPv4 для preview…</p>
|
||||
: <p role="status">{sourceCurrent.ipv4 === null ? "IPv4 для preview не определён." : "IPv4 для preview: " + sourceCurrent.ipv4}</p>}
|
||||
<p>Preview справочный. Backend повторно определяет источник при запуске; пустой результат не подтверждает исходный адрес команды.</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── tool selector + config ── */}
|
||||
<OpsPanel contentClassName="pt-4 pb-4 px-4 flex flex-col gap-4">
|
||||
|
||||
|
||||
Reference in new issue
Block a user