fix(ui): показывать частичные сбои опроса VXLAN

This commit is contained in:
Denozordec committed 2026-09-30 09:42:43 +07:00
1 parent 4dc2ee2129
commit e163a9ed9d
9 files changed
+120 -41

No files matched your search

+14 -1
View File
@@ -1,5 +1,5 @@
import assert from "node:assert/strict"
import { mapVxlanRow } from "./vxlan-live.js"
import { mapVxlanRow, pollVxlanServers } from "./vxlan-live.js"
const server = {
id: 7,
@@ -41,3 +41,16 @@ assert.deepEqual(row.remoteVteps, ["10.0.1.1", "10.0.2.1"])
assert.equal(row.vtepIp, "10.0.0.1")
console.log("vxlan-live.test.ts: ok")
const mixed = await pollVxlanServers([server, { ...server, id: 8, name: "failed" }], async s => {
if (s.id === 8) throw new Error("device unavailable")
return [row]
})
assert.deepEqual(mixed.tunnels, [row])
assert.deepEqual(mixed.failures, [{ serverId: "8", serverName: "failed", error: "device unavailable" }])
const empty = await pollVxlanServers([server], async () => [])
assert.deepEqual(empty, { tunnels: [], failures: [] })
const failed = await pollVxlanServers([server], async () => { throw new Error("all failed") })
assert.equal(failed.tunnels.length, 0)
assert.equal(failed.failures.length, 1)
console.log("vxlan polling: mixed/empty/all-failed ok")
+22 -19
View File
@@ -93,33 +93,36 @@ async function fetchVxlanForServer(server: ServerRow): Promise<VxlanTunnelLive[]
const client = MikrotikClient.fromServer(server)
const [vxRaw, vtepRaw] = await Promise.all([
client.get<RosVxlan[]>("/interface/vxlan"),
client.get<RosVxlanVtep[]>("/interface/vxlan/vteps").catch(() => [] as RosVxlanVtep[]),
client.get<RosVxlanVtep[]>("/interface/vxlan/vteps"),
])
const list = Array.isArray(vxRaw) ? vxRaw : []
const vteps = Array.isArray(vtepRaw) ? vtepRaw : []
if (!Array.isArray(vxRaw) || !Array.isArray(vtepRaw)) throw new Error("Некорректный ответ VXLAN устройства")
const list = vxRaw
const vteps = vtepRaw
return list.map((vx, idx) => mapVxlanRow(server, vx, vteps, idx))
}
export async function listVxlanTunnels(): Promise<VxlanTunnelLive[]> {
export async function pollVxlanServers(
serverRows: ServerRow[],
fetchServer: (server: ServerRow) => Promise<VxlanTunnelLive[]> = fetchVxlanForServer,
): Promise<{ tunnels: VxlanTunnelLive[]; failures: Array<{ serverId: string; serverName: string; error: string }> }> {
const results = await Promise.all(serverRows.map(async server => {
try { return { tunnels: await fetchServer(server), failures: [] } }
catch (error) { return { tunnels: [], failures: [{ serverId: String(server.id), serverName: server.name, error: error instanceof Error ? error.message : String(error) }] } }
}))
return { tunnels: results.flatMap(result => result.tunnels), failures: results.flatMap(result => result.failures) }
}
export async function listVxlanResult() {
const enabledServers = await db.select().from(servers).where(eq(servers.enabled, true))
const results = await Promise.all(
enabledServers.map(async (server) => {
try {
return await fetchVxlanForServer(server)
} catch {
return [] as VxlanTunnelLive[]
}
}),
)
return results.flat()
return pollVxlanServers(enabledServers)
}
export async function listVxlanTunnels(): Promise<VxlanTunnelLive[]> {
return (await listVxlanResult()).tunnels
}
export async function listVxlanTunnelsForServer(server: ServerRow): Promise<VxlanTunnelLive[]> {
try {
return await fetchVxlanForServer(server)
} catch {
return []
}
return fetchVxlanForServer(server)
}
export async function countVxlanTunnels(): Promise<number> {