fix(ui): сохранять подтверждённый снимок пути при ошибке API

This commit is contained in:
Denozordec committed 2026-10-04 00:07:21 +07:00
1 parent 55c9349677
commit 5fdd6ef58c
9 files changed
+85 -53

No files matched your search

+12 -25
View File
@@ -1,3 +1,4 @@
import {readProbeOutput} from "@/lib/probe-response"
import type { GreTunnel, Server, WanUplink } from "@/lib/data"
import {
assignSpeedProbesToGreTunnels,
@@ -152,18 +153,6 @@ function chooseActiveWan(
return wans[0] ?? null
}
function syntheticWanForHome(home: Server): WanUplink {
return {
id: `wan-auto-${home.id}`,
name: "WAN-AUTO",
isp: "auto",
iface: "auto",
ip: home.host || "0.0.0.0",
maxDl: 100,
maxUl: 100,
}
}
function bestJhForWan(
home: Server,
wan: WanUplink,
@@ -293,11 +282,13 @@ export function buildDashboardInternetPath(args: {
}
: null
const activeWan = chooseActiveWan(
const observedRoute=Boolean(runtime?.defaultGateway||args.routeLookupByServerId[home.id]?.gateway)
const routeKnown=runtime!=null&&args.routeLookupByServerId[home.id]!=null
const activeWan = observedRoute ? chooseActiveWan(
home,
args.routeLookupByServerId[home.id] ?? null,
runtime,
) ?? syntheticWanForHome(home)
) : null
const currentJh = activeWan ? bestJhForWan(home, activeWan, jhs, args.probes) : null
const currentExit = currentJh ? bestExitForJh(currentJh, exits, args.probes) : null
const currentPath: InternetPathRoute | null = activeWan
@@ -308,7 +299,7 @@ export function buildDashboardInternetPath(args: {
: null
const pathState: InternetPathViewModel["pathState"] =
primaryPath && currentPath
!routeKnown||home.status==="unknown"||(currentJh?.status==="unknown")||(currentExit?.status==="unknown")?"unknown":primaryPath && currentPath
// Нормальный production-кейс: часть трафика идет через BGP (JH→EN),
// часть — напрямую в провайдера WAN uplink.
? "healthy"
@@ -431,15 +422,15 @@ export function buildDashboardInternetPath(args: {
directWan: {
enabled: Boolean(runtime?.defaultGateway || args.routeLookupByServerId[home.id]?.gateway),
gateway: runtime?.defaultGateway ?? args.routeLookupByServerId[home.id]?.gateway ?? null,
iface: runtime?.defaultInterface ?? activeWan.iface ?? null,
iface: runtime?.defaultInterface ?? activeWan?.iface ?? null,
leasedIp:
runtime?.uplinks.find((u) => u.isDefault)?.leasedIp
?? runtime?.uplinks.find((u) => norm(u.iface) === norm(activeWan.iface))?.leasedIp
?? runtime?.uplinks.find((u) => norm(u.iface) === norm(activeWan?.iface))?.leasedIp
?? null,
provider:
runtime?.uplinks.find((u) => u.isDefault)?.isp
?? runtime?.uplinks.find((u) => norm(u.iface) === norm(activeWan.iface))?.isp
?? activeWan.isp
?? runtime?.uplinks.find((u) => norm(u.iface) === norm(activeWan?.iface))?.isp
?? activeWan?.isp
?? null,
},
}
@@ -449,8 +440,7 @@ export async function resolveDefaultRouteLookup(
apiFetch: <T>(path: string, init?: RequestInit) => Promise<T>,
serverId: string,
): Promise<RouteLookupResult | null> {
try {
const payload = await apiFetch<{ output?: string }>(`/api/servers/${serverId}/probes/run`, {
const payload = await apiFetch<unknown>(`/api/servers/${serverId}/probes/run`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -458,8 +448,5 @@ export async function resolveDefaultRouteLookup(
target: INTERNET_TARGET,
}),
})
return parseRouteLookupOutput(payload.output ?? "")
} catch {
return null
}
return parseRouteLookupOutput(readProbeOutput(payload))
}