fix(ui): сохранить snapshot speed при неизвестном исходе записи

This commit is contained in:
Denozordec committed 2026-10-08 08:48:58 +07:00
1 parent f408afba20
commit 96fa910804
8 files changed
+57 -4

No files matched your search

+2 -1
View File
@@ -2,6 +2,7 @@
import { publishSpeedProbeSnapshots } from "@/lib/speed-probe-snapshot"
import { parseSpeedRunResponse } from "@/lib/speed-run-response"
import { isSpeedPersistenceUnknown } from "@/lib/speed-persistence-outcome"
import { dashboardProbeOverviewSchema } from "@/lib/dashboard-probes"
@@ -1811,7 +1812,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
lines: [`status: error`, message],
}) : r))
setSpeedError(message)
setSpeedProbes((prev) => prev.map((p) => p.id === probe.id ? ({
if (!isSpeedPersistenceUnknown(e, runId)) setSpeedProbes((prev) => prev.map((p) => p.id === probe.id ? ({
...p,
lastRunAt: new Date().toISOString(),
lastStatus: "error",
+4
View File
@@ -113,3 +113,7 @@ BGP-prefix evaluator, отдельное live GRE расписание и recove
## PG-8 — 2026-10-08
12.5.19 [realPG/nativeTCP матрица](ux-ui/acceptance/pg8-speed-2026-10-08.json) подтвердилаINSERTrollback иclient-sideackfault послереальногоCOMMIT,безложногоfailurewrite/повтора. API502unknown/runId;scheduledreceiptokfalse,история/snapshotdoneсохранены.18scheduler/16persistence/HTTP-RBAC/build passed. Это не физическийTCPdisconnect;browserunknown-speed/deploymentpatch ещё12.5.20. Основнойbackend4c12c55 сохраняется.
## Локальный snapshot guard — 2026-10-08
12.5.20 сохраняетlastconfirmedspeed snapshot дляunknown502/совпадающегоrunId.2unit tests/frontendtypecheck passed;browserunknownUX ещёнепроверен,patchнеразвёрнут. Backend4c12c55/frontend673e5ba прежние. Следующий12.5.21 — build/browserunknown/deploymentобоихобразов.
+1 -1
View File
@@ -1,6 +1,6 @@
# План реализации UX/UI по пятичасовым окнам
Актуальное продолжение 2026-10-08:12.5.19 завершён — realPG/nativeTCP подтвердилиINSERTrollback иclient-sideackloss послеCOMMIT; APIunknown/runId безложногofailurewrite/повтора. Schedulerreceipt исправлен: unknownpersistence неложныйok.18scheduler/16persistence/HTTP-RBAC/build passed. Основнойbackend4c12c55 сохраняется,patchнеразвёрнут. Следующий12.5.20 — deploymentpatch/browserunknown-speed иоставшиесяROS/Q/интеграции.
Актуальное продолжение 2026-10-08:12.5.20 завершёнлокально — unknown502/currentrunId не переписываетподтверждённыйsnapshot пробы.2unit tests/frontendtypecheck passed;временнаястроказапросаещёerror,полныйbrowserunknownUX открыт. Runtimebackend4c12c55/frontend673e5ba прежние. Следующий12.5.21 — build/browserunknownspeed/deploymentобоихобразов.
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-07. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
+9 -1
View File
@@ -1,6 +1,6 @@
# UX/UI: журнал реализации
Актуальное продолжение 2026-10-08:12.5.19 завершён — realPG/nativeTCP подтвердилиINSERTrollback иclient-sideackloss послеCOMMIT; APIunknown/runId безложногofailurewrite/повтора. Schedulerreceipt исправлен: unknownpersistence неложныйok.18scheduler/16persistence/HTTP-RBAC/build passed. Основнойbackend4c12c55 сохраняется,patchнеразвёрнут. Следующий12.5.20 — deploymentpatch/browserunknown-speed иоставшиесяROS/Q/интеграции.
Актуальное продолжение 2026-10-08:12.5.20 завершёнлокально — unknown502/currentrunId не переписываетподтверждённыйsnapshot пробы.2unit tests/frontendtypecheck passed;временнаястроказапросаещёerror,полныйbrowserunknownUX открыт. Runtimebackend4c12c55/frontend673e5ba прежние. Следующий12.5.21 — build/browserunknownspeed/deploymentобоихобразов.
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
@@ -34,6 +34,14 @@
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в описанных границах:12.3.83,main1186/1186,context221/221. Этап остаётся в работе: стенд12.5.1–3 развёрнут,bootstrap/smoke проверены;остальные сценарии12.5 не выполнены. |
## 12.5.20 — сохранение подтверждённого speed snapshot при unknown receipt (2026-10-08)
Приостатке5%окнавыполненнебольшойлокальныйблокпередdeployment. Frontendcatch раньше ставилlastStatuserror/новыйlastRunAt любойошибкеPOSTspeed-test,включаяunknowncommit. Теперьподтверждённыйsnapshot пробысохраняется,еслиApiClientError502 содержитoutcomeunknown иrunId текущегозапроса. ЧужойrunId/неправильныйpayload/403/обычнаяошибка нераспознаютсякакэтотисход. Существующееservererrorсообщениепоказывается;новыекомпоненты/композицияReUIне менялись. Временнаястрокасамогозапросапо-прежнемуимеетstatuserror; полныйunknown-state/browserUX ещёнужнопроверить.
Добавленыlib/speed-persistence-outcome.ts и2meaningfultests;подключенguardвuptime/page.tsx. Обаunit tests passed. ПервыйroottscподхватилкопиистарогоCI contextвignoredtmp ивернулисходныеошибкиэтихкопий. Повторныйполныйfrontendtypecheckсвременнымconfig,которыйсохраняетrootoptions/исключения иисключаетtmp,passed; основнойtsconfigне менялся. Diff-check passed. ReUI skillпрочитан: адаптациясуществующегоэкрана,безновойregistryinstallation/редизайна. Browserunknownspeed/productionbuild/deploymentвэтомблокенезапускались.
Основнойruntimebackend4c12c55/frontend673e5ba сохраняется;backendpatchf408afb иfrontendguardещёнеразвёрнуты. Следующий12.5.21 — собратьобаобновлённыхобраза,проверитьbrowserunknownspeed/историю иразвернутьпослепроверок. Журналобновлён;локальныйкоммитбезpush.
## 12.5.19 — speed persistence, ошибка INSERT и потерянное подтверждение commit (2026-10-08)
Выявленриск: общийcatch native run послеошибкиpersist запускалrecordSpeedTestFailure, хотяbandwidth-test ужезавершён. Послеcommitackloss это моглоподменитьsnapshot/log ложнымerror (особенноеслиrunId не былпередан). ДобавленSpeedRunPersistenceUnknown(actualrunId,cause) тольконаграничепубликацииуспешногоnativeрезультата. Routeвозвращает502/outcomeunknown/runId/просьбупроверитьисторию; failurewriterне вызывается. Плановыйrun тоже не записываетложныйfailedresult. Исходныйdrivercause сохранёнвError,публичныйreceipt не раскрываетSQL/credentials.
+9 -1
View File
@@ -1,6 +1,6 @@
# Этап 12: итоговая приёмка UX/UI
Актуальное продолжение 2026-10-08:12.5.19 завершён — realPG/nativeTCP подтвердилиINSERTrollback иclient-sideackloss послеCOMMIT; APIunknown/runId безложногofailurewrite/повтора. Schedulerreceipt исправлен: unknownpersistence неложныйok.18scheduler/16persistence/HTTP-RBAC/build passed. Основнойbackend4c12c55 сохраняется,patchнеразвёрнут. Следующий12.5.20 — deploymentpatch/browserunknown-speed иоставшиесяROS/Q/интеграции.
Актуальное продолжение 2026-10-08:12.5.20 завершёнлокально — unknown502/currentrunId не переписываетподтверждённыйsnapshot пробы.2unit tests/frontendtypecheck passed;временнаястроказапросаещёerror,полныйbrowserunknownUX открыт. Runtimebackend4c12c55/frontend673e5ba прежние. Следующий12.5.21 — build/browserunknownspeed/deploymentобоихобразов.
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
@@ -1146,3 +1146,11 @@ SchedulerSnapshotError раньшеигнорировалruns[].okfalse уuptime
Матрицапотребоваладиагностикиharness: первыйwrapperнеподдерживалPool.connectcallback иупалдонативныхтестов; перваяполнаяnativeматрицавыявилаschedulerok дефект; rerunполучил500 приcallback instrumentation. Добавленыcallbackbypass/BEGINreset,разовыеmanualrunIDs иdiagnosticerrorhandler; окончательнаяматрицапрошла,проверяемые502обработаныproductionroute,неdiagnostic handler. Выполнялисьручныеповторыпослеисправленияharness/classifier; это неавтоповторвнутриоперации. ФинальныеcompiledJSиpatchSHA совпалислокальными. Temporaryprobe/trigger/function удалены,count0; historicaltest runs сохраненывпроверочнойБД,probeassociationпослеcleanupFK=null. Temporarycontainer--rm/consumers/pool остановлены,mainhealth4c12c55ok/БДнеизменена,RouterOSconfigurationне менялась.
Локально18scheduler tests (включаяновыйunknownspeedreceipt),16speedpersistence tests,HTTPcommand/RBAC/unknownrunId-no-failure-write test иcontracts/backend build прошли; diff-check passed. Старыйосновнойruntime4c12c55 ещёбезэтогопatch. BrowserunknowncommitUX/физическийnetworkloss/deploymentpatch иостальной12.5 открыты. Остатокпятичасовоголимитапоследнейпроверки9%;новыйкрупныйблокненачат. Следующий12.5.20 — собрать/deploypatch иbrowserunknown-speed,затемROS/Q/integrationпротокол. Локальныйкоммитбезpush.
## 12.5.20 — сохранение подтверждённого speed snapshot при unknown receipt (2026-10-08)
Приостатке5%окнавыполненнебольшойлокальныйблокпередdeployment. Frontendcatch раньше ставилlastStatuserror/новыйlastRunAt любойошибкеPOSTspeed-test,включаяunknowncommit. Теперьподтверждённыйsnapshot пробысохраняется,еслиApiClientError502 содержитoutcomeunknown иrunId текущегозапроса. ЧужойrunId/неправильныйpayload/403/обычнаяошибка нераспознаютсякакэтотисход. Существующееservererrorсообщениепоказывается;новыекомпоненты/композицияReUIне менялись. Временнаястрокасамогозапросапо-прежнемуимеетstatuserror; полныйunknown-state/browserUX ещёнужнопроверить.
Добавленыlib/speed-persistence-outcome.ts и2meaningfultests;подключенguardвuptime/page.tsx. Обаunit tests passed. ПервыйroottscподхватилкопиистарогоCI contextвignoredtmp ивернулисходныеошибкиэтихкопий. Повторныйполныйfrontendtypecheckсвременнымconfig,которыйсохраняетrootoptions/исключения иисключаетtmp,passed; основнойtsconfigне менялся. Diff-check passed. ReUI skillпрочитан: адаптациясуществующегоэкрана,безновойregistryinstallation/редизайна. Browserunknownspeed/productionbuild/deploymentвэтомблокенезапускались.
Основнойruntimebackend4c12c55/frontend673e5ba сохраняется;backendpatchf408afb иfrontendguardещёнеразвёрнуты. Следующий12.5.21 — собратьобаобновлённыхобраза,проверитьbrowserunknownspeed/историю иразвернутьпослепроверок. Журналобновлён;локальныйкоммитбезpush.
+4
View File
@@ -121,3 +121,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 [email protected]
## Isolated PG-8 speed — 2026-10-08
12.5.19 [INSERTfailure/realCOMMITackfault/scheduledreceipt](ux-ui/acceptance/pg8-speed-2026-10-08.json) passedнаmmapp_acceptance_20261007/source4c12c55+worktreepatch среальнымиCHRtransmit3s. Temporaryprobe/trigger/function удалены,историческиетестовыерезультатыосталисьвпроверочнойБД. Основнойruntime4c12c55healthy/БДнеизменена;patchещёнеразвёрнут. Следующий12.5.20 — deployment/browserunknown-speed.
## Локальный snapshot guard — 2026-10-08
12.5.20 сохраняетlastconfirmedspeed snapshot дляunknown502/совпадающегоrunId.2unit tests/frontendtypecheck passed;browserunknownUX ещёнепроверен,patchнеразвёрнут. Backend4c12c55/frontend673e5ba прежние. Следующий12.5.21 — build/browserunknown/deploymentобоихобразов.
+19
View File
@@ -0,0 +1,19 @@
import assert from "node:assert/strict"
import { test } from "node:test"
import { ApiClientError } from "../shared/api/http-client"
import { isSpeedPersistenceUnknown } from "./speed-persistence-outcome"
test("matching unknown persistence receipt preserves the confirmed snapshot", () => {
assert.equal(isSpeedPersistenceUnknown(new ApiClientError("unknown", 502, { outcome: "unknown", runId: "current" }), "current"), true)
})
test("other operations, malformed responses and ordinary failures cannot masquerade as unknown persistence", () => {
for (const error of [
Error("unknown"),
new ApiClientError("unknown", 502, { outcome: "unknown", runId: "other" }),
new ApiClientError("unknown", 502, { outcome: "unknown" }),
new ApiClientError("unknown", 502, { outcome: "failed", runId: "current" }),
new ApiClientError("forbidden", 403, { outcome: "unknown", runId: "current" }),
new ApiClientError("bad body", 502, null),
]) assert.equal(isSpeedPersistenceUnknown(error, "current"), false)
})
+9
View File
@@ -0,0 +1,9 @@
import { ApiClientError } from "@/shared/api/http-client"
/** Preserve the last confirmed snapshot only for this operation's explicit unknown receipt. */
export function isSpeedPersistenceUnknown(error: unknown, runId: string): boolean {
if (!(error instanceof ApiClientError) || error.status !== 502) return false
if (!error.payload || typeof error.payload !== "object") return false
const payload = error.payload as { outcome?: unknown; runId?: unknown }
return payload.outcome === "unknown" && payload.runId === runId
}