fix(ui): показывать неопределённый исход speed и сверять историю

This commit is contained in:
Denozordec committed 2026-10-08 08:57:54 +07:00
1 parent 96fa910804
commit 8782054078
8 files changed
+145 -11

No files matched your search

+20 -7
View File
@@ -707,7 +707,7 @@ interface SpeedTestRun {
durationSec: number
txAvgMbps: number | null
rxAvgMbps: number | null
status: "running" | "done" | "error"
status: "running" | "done" | "error" | "unknown"
command: string
lines: string[]
afterBtPing?: { rttMs: number | null; lossPct: number | null; error: string | null } | null
@@ -1077,7 +1077,14 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
const [probeRttChartOpen, setProbeRttChartOpen] = useState<Record<string, boolean>>({})
const [speedBusy, setSpeedBusy] = useState(false)
const [speedError, setSpeedError] = useState<string | null>(null)
const [speedUnknownRunId, setSpeedUnknownRunId] = useState<string | null>(null)
const [speedRuns, setSpeedRuns] = useState<SpeedTestRun[]>([])
useEffect(() => {
if (speedUnknownRunId && speedRuns.some(run => run.id === speedUnknownRunId && (run.status === "done" || run.status === "error"))) {
setSpeedUnknownRunId(null)
setSpeedError(null)
}
}, [speedRuns, speedUnknownRunId])
const [speedProbes, setSpeedProbes] = useState<SpeedProbeRow[]>([])
const speedReadRevision = useRef(0)
const [speedReads, setSpeedReads] = useState<Record<"probes" | "history", { receivedAt: number | null; error: string | null }>>({ probes: { receivedAt: null, error: null }, history: { receivedAt: null, error: null } })
@@ -1182,7 +1189,10 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
srcInterfaceAddress: r.srcInterfaceAddress ?? null,
dstInterfaceAddress: r.dstInterfaceAddress ?? null,
}))
if (current()) setSpeedRuns(rows)
if (current()) setSpeedRuns(previous => [
...previous.filter(run => (run.status === "running" || run.status === "unknown") && !rows.some(row => row.id === run.id)),
...rows,
])
}),
])
}, [apiFetch, liveApi])
@@ -1687,6 +1697,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
overviewReqRef.current++
const context = ++saveContext.current
setSpeedError(null)
setSpeedUnknownRunId(null)
setSpeedBusy(true)
const durationSec = Math.max(3, Number.parseInt(probe.durationSec, 10) || 10)
const runId = `speed-${Date.now()}`
@@ -1806,13 +1817,15 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
} catch (e) {
if (context !== saveContext.current) return
const message = serverOperationError(e)
const persistenceUnknown = isSpeedPersistenceUnknown(e, runId)
setSpeedUnknownRunId(persistenceUnknown ? runId : null)
setSpeedRuns((prev) => prev.map((r) => r.id === runId ? ({
...r,
status: "error",
lines: [`status: error`, message],
status: persistenceUnknown ? "unknown" : "error",
lines: [`status: ${persistenceUnknown ? "unknown" : "error"}`, message],
}) : r))
setSpeedError(message)
if (!isSpeedPersistenceUnknown(e, runId)) setSpeedProbes((prev) => prev.map((p) => p.id === probe.id ? ({
if (!persistenceUnknown) setSpeedProbes((prev) => prev.map((p) => p.id === probe.id ? ({
...p,
lastRunAt: new Date().toISOString(),
lastStatus: "error",
@@ -2107,7 +2120,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
{/* ── error ── */}
{speedError && (
<div className="mx-6 mt-4">
<Alert variant="destructive" className="py-2 text-xs">
<Alert variant={speedUnknownRunId ? "default" : "destructive"} className="py-2 text-xs">
<AlertCircleIcon />
<AlertDescription>{speedError}</AlertDescription>
</Alert>
@@ -2160,7 +2173,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
const run = speedRuns.find((r) =>
sameSpeedMeasurement(r, probe),
)
const useRun = run && (run.status === "running" || (
const useRun = run && run.status !== "unknown" && (run.status === "running" || (
probe.lastStatus != null && probe.lastRunAt != null && run.startedAt >= Date.parse(probe.lastRunAt)
))
const viewStatus = useRun ? run.status : (probe.lastStatus === "error" || probe.lastStatus === "done" ? probe.lastStatus : null)