fix(uptime): проверять завершение теста перед записью успеха
This commit is contained in:
1 parent
9d5959601f
commit
fb32f87d33
6 files changed
+62
-2
No files matched your search
@@ -0,0 +1,24 @@
|
||||
import { test } from "node:test"
|
||||
import assert from "node:assert/strict"
|
||||
import { assertBandwidthTestCompleted } from "./bandwidth-test-status.js"
|
||||
import { readBandwidthTestRates } from "./bandwidth-test-rates.js"
|
||||
|
||||
test("confirmed completion preserves one-direction unknown and explicit zero", () => {
|
||||
const rows = [{ status: "connecting" }, { status: "running", "rx-current": "20Mbps" }, { status: "done testing", "rx-total-average": "0bps" }]
|
||||
assert.doesNotThrow(() => assertBandwidthTestCompleted(rows))
|
||||
const result = readBandwidthTestRates(rows)
|
||||
assert.equal(result.txAvgMbps, null)
|
||||
assert.equal(result.rxAvgMbps, 0)
|
||||
assert.doesNotThrow(() => assertBandwidthTestCompleted([{ status: "done testing" }, { "tx-total-average": "10Mbps" }]))
|
||||
})
|
||||
test("all native failures reject even with valid rates or a subsequent success marker", () => {
|
||||
for (const status of ["authentication failed", "can not connect", "can not start test", "remote is busy", "test unsupported", "disconnected"]) {
|
||||
assert.throws(() => assertBandwidthTestCompleted([{ status, "tx-total-average": "50Mbps" }]))
|
||||
assert.throws(() => assertBandwidthTestCompleted([{ status }, { status: "done testing" }]))
|
||||
}
|
||||
})
|
||||
test("missing, incomplete and malformed native replies never count as completed", () => {
|
||||
for (const raw of [null, {}, [], [null], [[]], [{ status: 8 }], [{ status: "" }], [{ "tx-total-average": "50Mbps" }], [{ status: "running" }], [{ status: "connecting" }], [{ status: "done testing" }, { status: "running" }], [{ status: "done testing" }, { status: "future status" }], [{ status: "done testing", error: "failure" }], [{ status: "done testing", failure: "failure" }], [{ status: "done testing", "!trap": true }]]) {
|
||||
assert.throws(() => assertBandwidthTestCompleted(raw), /Результат операции неизвестен/)
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
const failures: Record<string, string> = {
|
||||
"authentication failed": "RouterOS отклонил авторизацию bandwidth-test",
|
||||
"can not connect": "Bandwidth-test не смог подключиться к назначению",
|
||||
"can not start test": "RouterOS не смог начать bandwidth-test",
|
||||
"remote is busy": "Устройство назначения занято",
|
||||
"test unsupported": "Устройство назначения не поддерживает bandwidth-test",
|
||||
"disconnected": "Соединение bandwidth-test прервано до завершения",
|
||||
}
|
||||
|
||||
/** HTTP success is insufficient: the last reported native state must confirm completion. */
|
||||
export function assertBandwidthTestCompleted(raw: unknown): asserts raw is Array<Record<string, unknown>> {
|
||||
const unknown = () => new Error("RouterOS не подтвердил завершение bandwidth-test. Результат операции неизвестен")
|
||||
if (!Array.isArray(raw) || !raw.length) throw unknown()
|
||||
let lastStatus: string | undefined
|
||||
for (const row of raw) {
|
||||
if (!row || typeof row !== "object" || Array.isArray(row)) throw unknown()
|
||||
if ("error" in row || "failure" in row || "!trap" in row) throw unknown()
|
||||
if (row.status === undefined) continue
|
||||
if (typeof row.status !== "string" || !row.status.trim()) throw unknown()
|
||||
const status = row.status.trim().toLowerCase()
|
||||
if (Object.hasOwn(failures, status)) throw new Error(failures[status])
|
||||
lastStatus = status
|
||||
}
|
||||
if (lastStatus !== "done testing") throw unknown()
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import type { RosIpAddress } from "../types/server.js"
|
||||
import { withBtestNodeLocks } from "./btest-node-locks.js"
|
||||
import { MikrotikClient } from "./mikrotik.js"
|
||||
import { parsePing } from "./uptime-collector.js"
|
||||
import { assertBandwidthTestCompleted } from "./bandwidth-test-status.js"
|
||||
import { readBandwidthTestRates } from "./bandwidth-test-rates.js"
|
||||
|
||||
function firstUsableIpOnInterface(rows: RosIpAddress[], iface: string): string {
|
||||
@@ -106,6 +107,7 @@ export async function executeBandwidthSpeedTestInner(params: SpeedTestRunParams)
|
||||
direction,
|
||||
durationSec,
|
||||
})
|
||||
assertBandwidthTestCompleted(rows)
|
||||
const { txAvgMbps: txFinal, rxAvgMbps: rxFinal, txSeries, rxSeries } = readBandwidthTestRates(rows)
|
||||
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 3000))
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# План реализации UX/UI по пятичасовым окнам
|
||||
|
||||
Актуальное продолжение 2026-10-07: 12.3.73 завершён: nullable bandwidth producer/POST consumer, проверка runId, 16pure/71browser/8context и frontend/backend build. Следующий12.3.74: terminal confirmation RouterOS; затем75OSPF RX/TX mapping,76mobile pinned-column readable geometry. Команды/права не менять,12.5 отдельно.
|
||||
Актуальное продолжение 2026-10-07: 12.3.74 завершён: backend проверяет native terminal status перед Ping/DB success write,16pure и backend build. Следующий12.3.75: OSPF RX/TX mapping; затем76mobile pinned-column readable geometry. Команды/права не менять,12.5 отдельно.
|
||||
|
||||
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-04. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# UX/UI: журнал реализации
|
||||
|
||||
Актуальное продолжение 2026-10-07: 12.3.73 завершён: nullable bandwidth producer/POST consumer, проверка runId, 16pure/71browser/8context и frontend/backend build. Следующий12.3.74: terminal confirmation RouterOS; затем75OSPF RX/TX mapping,76mobile pinned-column readable geometry. Команды/права не менять,12.5 отдельно.
|
||||
Актуальное продолжение 2026-10-07: 12.3.74 завершён: backend проверяет native terminal status перед Ping/DB success write,16pure и backend build. Следующий12.3.75: OSPF RX/TX mapping; затем76mobile pinned-column readable geometry. Команды/права не менять,12.5 отдельно.
|
||||
|
||||
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения.
|
||||
|
||||
|
||||
@@ -817,3 +817,12 @@ CPU final:1000routes13.3ms;100000(10×100×100)49.7ms;100000(100×10×100)44.0ms
|
||||
7 pure parser/DTO +9 isolated scheduler journal tests прошли.71 main browser (uptime-links, speed-data, large-speed-history),8 context прошли; non-incremental TypeScript, targeted lint (9 существующих предупреждений uptime,0 errors), backend и frontend production build успешны. Первые два новых браузерных прогона обнаружили неверный KPI role selector и неоднозначность одинаковой подписи в истории/строке; selectors уточнены, финальный связанный профиль полностью passed. Historical large-speed-history-320 PNG восстановлен.
|
||||
|
||||
Следующий74: native terminal status ещё не проверяется перед done/DB write.75OSPF direction и76mobile metric geometry остаются. DTO доказывает целостность ответа, но не факт выполнения на устройстве. Реальная RouterOS/PG приёмка12.5 отдельно.
|
||||
|
||||
|
||||
## 12.3.74 — подтверждённое завершение bandwidth-test
|
||||
|
||||
2026-10-07. Pure guard проверяет структуру native rows, все известные failure statuses и последний сообщённый status. Только done testing допускает дальнейший расчёт, after-ping и DB success write. Connecting/running, отсутствие статуса, неизвестный status, malformed response или error/failure/trap marker отклоняются с неизвестным результатом; native failures имеют краткие русские сообщения. Числовой enum не принимается как строковое подтверждение. Подтверждённый one-direction result может иметь null на другой стороне и0 на измеренной.
|
||||
|
||||
16 pure tests (3status,4rates,9scheduler) и backend build passed. Проверка placement/callers по source: HTTP и scheduled collection используют общий execute, их catch вызывает прежний failure recorder, который сохраняет старые probe averages и пишет error run с nullable rates. Полная DB/network orchestration не запускалась; это source review и pure guard tests, а не внешняя приёмка. Команда bandwidth-test и её параметры, locks, routing rules, permissions и DB schema не менялись.
|
||||
|
||||
Источник native statuses: [RouterOS CLI bandwidth-test](https://manual.mikrotik.com/docs/cli-reference/tool/bandwidth-test/). Последний reported done допускает последующие rows без status, но любые failure markers отклоняются даже после completion. Реальный REST shape/версия RouterOS и PG writes требуют12.5. Следующие75direction OSPF и76mobile geometry.
|
||||
Reference in new issue
Block a user