fix(api): сохранять неизвестные показатели BFD и OSPF
This commit is contained in:
1 parent
47dcd89b3c
commit
e3791f3496
13 files changed
+136
-44
No files matched your search
@@ -1,8 +1,11 @@
|
||||
import type { MikrotikClient } from "./mikrotik.js"
|
||||
import type { OspfNeighborRead, OspfInterfaceRead, OspfInstanceRead, BfdSessionRead, OspfRouteRead } from "../types/server.js"
|
||||
export type NullableFields<T, K extends keyof T> = Omit<T, K> & { [P in K]: T[P] | null }
|
||||
export type CatalogNeighbor = NullableFields<OspfNeighborRead, "priority" | "stateChanges">
|
||||
export type CatalogBfdSession = NullableFields<BfdSessionRead, "multiplier" | "txInterval" | "rxInterval" | "holdTime" | "packetsRx" | "packetsTx" | "stateChanges">
|
||||
export interface OspfCatalogCollections {
|
||||
neighbors: OspfNeighborRead[]; interfaces: OspfInterfaceRead[]; instances: OspfInstanceRead[];
|
||||
bfdSessions: BfdSessionRead[]; routes: OspfRouteRead[];
|
||||
neighbors: CatalogNeighbor[]; interfaces: OspfInterfaceRead[]; instances: OspfInstanceRead[];
|
||||
bfdSessions: CatalogBfdSession[]; routes: OspfRouteRead[];
|
||||
}
|
||||
export const emptyOspfCatalog = (): OspfCatalogCollections => ({ neighbors: [], interfaces: [], instances: [], bfdSessions: [], routes: [] })
|
||||
export async function readOspfCatalogRaw(client: Pick<MikrotikClient, "getOspfNeighbors" | "getOspfAreas" | "getOspfInterfaceTemplates" | "getOspfInstances" | "getBfdSessions" | "getIpRoutes">) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { observedInteger, observedDurationMs } from "./ospf-observed-values.js"
|
||||
for (const raw of [undefined, "", " ", "1x", "-1", "1.5", "9007199254740992"]) assert.equal(observedInteger(raw), null)
|
||||
assert.equal(observedInteger("0"), 0); assert.equal(observedInteger("255", 0, 255), 255); assert.equal(observedInteger("256", 0, 255), null)
|
||||
for (const raw of [undefined, "", "-1s", "12junk", "200", "1s2s", "60:00", "00:99:00", "1s junk"]) assert.equal(observedDurationMs(raw), null)
|
||||
for (const [raw, ms] of [["0ms", 0], ["0", 0], ["1us", 0.001], ["1s200ms", 1200], ["1h2m3s", 3723000], ["01:02:03.5", 3723500], ["02:03", 123000]] as const) assert.equal(observedDurationMs(raw), ms)
|
||||
console.log("OSPF observed values: absent/zero/invalid/unsafe/units/clock passed")
|
||||
@@ -0,0 +1,28 @@
|
||||
/** Values read from RouterOS; absence is not a measured zero. */
|
||||
export function observedInteger(value: string | undefined, min = 0, max = Number.MAX_SAFE_INTEGER): number | null {
|
||||
if (value === undefined || !/^\d+$/.test(value.trim())) return null
|
||||
const number = Number(value.trim())
|
||||
return Number.isSafeInteger(number) && number >= min && number <= max ? number : null
|
||||
}
|
||||
/** RouterOS time in milliseconds. Bare numbers are ambiguous, except explicit zero. */
|
||||
export function observedDurationMs(value: string | undefined): number | null {
|
||||
const text = value?.trim()
|
||||
if (!text) return null
|
||||
if (text === "0") return 0
|
||||
const clock = /^(?:(\d+):)?(\d{1,2}):(\d{2})(\.\d+)?$/.exec(text)
|
||||
if (clock) {
|
||||
const [, hours = "0", minutes, seconds, fraction = ""] = clock
|
||||
if (Number(minutes) >= 60 || Number(seconds) >= 60) return null
|
||||
const ms = (Number(hours) * 3600 + Number(minutes) * 60 + Number(seconds + fraction)) * 1000
|
||||
return Number.isFinite(ms) && ms <= Number.MAX_SAFE_INTEGER ? ms : null
|
||||
}
|
||||
const units: Record<string, number> = { w: 604800000, d: 86400000, h: 3600000, m: 60000, s: 1000, ms: 1, us: 0.001, ns: 0.000001 }
|
||||
const pattern = /(\d+(?:\.\d+)?)(ms|us|ns|w|d|h|m|s)/g
|
||||
let cursor = 0, total = 0
|
||||
const seen = new Set<string>()
|
||||
for (const part of text.matchAll(pattern)) {
|
||||
if (part.index !== cursor || seen.has(part[2])) return null
|
||||
seen.add(part[2]); cursor += part[0].length; total += Number(part[1]) * units[part[2]]
|
||||
}
|
||||
return cursor === text.length && Number.isFinite(total) && total <= Number.MAX_SAFE_INTEGER ? total : null
|
||||
}
|
||||
Reference in new issue
Block a user