fix(api): исключить выключенные серверы из мониторинга

This commit is contained in:
Denozordec committed 2026-10-07 23:37:06 +07:00
1 parent f3e205950f
commit 4c12c55c9d
10 files changed
+160 -18

No files matched your search

@@ -0,0 +1,11 @@
import { eq } from "drizzle-orm"
import { db } from "../db/index.js"
import { servers } from "../db/schema.js"
export async function listEnabledMonitoringServers() {
return db.select().from(servers).where(eq(servers.enabled, true))
}
export function assertMonitoringServersEnabled(...targets: { enabled: boolean }[]): void {
if (targets.some(server => !server.enabled)) throw new Error("Сервер отключён: включите его перед запуском теста")
}
@@ -1,6 +1,7 @@
import { eq, or } from "drizzle-orm"
import { eq } from "drizzle-orm"
import { listEnabledMonitoringServers } from "./monitoring-server-catalog.js"
import { db, dbAll, dbQuery } from "../db/index.js"
import { servers, serversApiPingSettings, serversRestPingSamples } from "../db/schema.js"
import { serversApiPingSettings, serversRestPingSamples } from "../db/schema.js"
import type { ServersRestPingRunSnapshot } from "../types/scheduler-run-snapshot.js"
import { SCHEDULER_RUN_SNAPSHOT_VERSION } from "../types/scheduler-run-snapshot.js"
import { MikrotikClient } from "./mikrotik.js"
@@ -21,12 +22,9 @@ async function getSettingsRow() {
return (await db.select().from(serversApiPingSettings).where(eq(serversApiPingSettings.id, 1)).limit(1))[0]
}
/** Как uptime: включённые в каталоге или Home Router (часто «выкл.» при доступе только из LAN). */
/** Same enabled-only policy as uptime. */
async function serversForRestProbe() {
return await db
.select()
.from(servers)
.where(or(eq(servers.enabled, true), eq(servers.type, "home-router")))
return listEnabledMonitoringServers()
}
export async function getServersApiPingSettings() {
+4 -7
View File
@@ -1,9 +1,9 @@
import { replacePingProbes } from "./ping-probe-replacement.js"
import type { PingProbeWrite } from "@mmapp/contracts"
import { and, asc, eq, gte, inArray, max, or, sql } from "drizzle-orm"
import { and, asc, eq, gte, inArray, max, sql } from "drizzle-orm"
import { listEnabledMonitoringServers } from "./monitoring-server-catalog.js"
import { db } from "../db/index.js"
import {
servers,
uptimeProbeSamples,
uptimeProbes,
uptimeResourceSamples,
@@ -95,12 +95,9 @@ export function parsePing(results: Array<{ time?: string; status?: string; sent?
return { avgRtt, loss, status }
}
/** Узлы с REST-опросом для uptime: включённые в каталоге или любой Home Router (см. /servers — HR часто «выкл.» при доступе только из LAN). */
/** Disabled excludes every server type from resource and ping collection. */
async function serversForUptimeRosPoll() {
return await db
.select()
.from(servers)
.where(or(eq(servers.enabled, true), eq(servers.type, "home-router")))
return listEnabledMonitoringServers()
}
async function lastProbeSampleTimes(): Promise<Map<string, string>> {
+5 -1
View File
@@ -87,6 +87,7 @@ export async function executeBandwidthSpeedTestInner(params: SpeedTestRunParams)
const src = (await db.select().from(servers).where(eq(servers.id, srcId)).limit(1))[0]
const dst = (await db.select().from(servers).where(eq(servers.id, dstId)).limit(1))[0]
if (!src || !dst) throw new Error("Server not found")
assertMonitoringServersEnabled(src, dst)
const protocol = params.protocol === "udp" ? "udp" : "tcp"
const direction = params.direction === "transmit" || params.direction === "receive" ? params.direction : "both"
@@ -284,7 +285,9 @@ export async function runScheduledSpeedProbesOnce(): Promise<SpeedScheduledRunSn
const sampledAt = new Date().toISOString()
const runs: SpeedRunSnapshot[] = []
const rows = await db.select().from(uptimeSpeedProbes).orderBy(asc(uptimeSpeedProbes.sortOrder))
const enabled = rows.filter((r) => r.enabled !== false && r.srcServerId !== r.dstServerId)
const enabledIds = new Set((await listEnabledMonitoringServers()).map(server => server.id))
const enabled = rows.filter((r) => r.enabled !== false && r.srcServerId !== r.dstServerId
&& enabledIds.has(r.srcServerId) && enabledIds.has(r.dstServerId))
const protocol = (p: (typeof enabled)[number]) => (p.protocol === "udp" ? "udp" : "tcp")
const direction = (p: (typeof enabled)[number]) =>
p.direction === "transmit" || p.direction === "receive" ? p.direction : "both"
@@ -356,3 +359,4 @@ export async function runScheduledSpeedProbesOnce(): Promise<SpeedScheduledRunSn
runs,
}
}
import { assertMonitoringServersEnabled, listEnabledMonitoringServers } from "./monitoring-server-catalog.js"
+4
View File
@@ -97,3 +97,7 @@ BGP-prefix evaluator, отдельное live GRE расписание и recove
## Restore исправлен — 2026-10-07
12.5.15 realAPI200/контрольархива/новыйID3 иinjectedCREATE INDEX400/rollback данных,sequence и1587constraints прошли: [evidence](ux-ui/acceptance/real-restore-fixed-2026-10-07.json). PG-3/4 принятывэтихграницах, Portal/UI/fullchecksum не проверены. Основнойruntime673e5ba сохранён; integratedPG-6/deployment ещёпредстоят. Приrestart ресурсныйcollector попыталсяопрашиватьdisabledserver3; исправление12.5.16.
## Политика выключенных серверов — 2026-10-07
12.5.16 по явномувыборупользователя убрал намеренноеHome Router исключение изuptime/RESTping; scheduledspeed игнорируетdisabledendpoint, manualspeedотказдосети. [RealPG/CHRматрица](ux-ui/acceptance/monitoring-enabled-2026-10-07.json) passed. Основнойruntime673e5ba не обновлён;integratedPG-6/deployment12.5.17 впереди.
+1 -1
View File
@@ -1,6 +1,6 @@
# План реализации UX/UI по пятичасовым окнам
Актуальное продолжение 2026-10-07:12.5.15 завершён — транзакционный partition-safe restore исправлен и прошёл realAPI200/контрольархива/новыйID3; injected CREATE INDEX failure400 сохранилданные/sequence/1587constraints.25tests,HTTP/JWT иbuild passed. Основнойruntime673e5ba не обновлён. Следующий12.5.16 — disabled-server collector defect, integrated PG-6 иdeployment; весьэтап12.5 остаётсяоткрытым.
Актуальное продолжение 2026-10-07:12.5.16 завершён появномувыборупользователя — disabled исключаетвсетипыизuptime/RESTping/scheduledspeed; ручнойspeedотказдосети. RealPG/CHRматрица3типовпрошла,0новыхdisabledсэмплов;HTTP/RBAC,16persistence tests иbuild passed. Runtime673e5ba не обновлён. Следующий12.5.17 — integratedPG-6 иdeployment; вся12.5 ещёоткрыта.
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-07. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
+13 -1
View File
@@ -1,6 +1,6 @@
# UX/UI: журнал реализации
Актуальное продолжение 2026-10-07:12.5.15 завершён — транзакционный partition-safe restore исправлен и прошёл realAPI200/контрольархива/новыйID3; injected CREATE INDEX failure400 сохранилданные/sequence/1587constraints.25tests,HTTP/JWT иbuild passed. Основнойruntime673e5ba не обновлён. Следующий12.5.16 — disabled-server collector defect, integrated PG-6 иdeployment; весьэтап12.5 остаётсяоткрытым.
Актуальное продолжение 2026-10-07:12.5.16 завершён появномувыборупользователя — disabled исключаетвсетипыизuptime/RESTping/scheduledspeed; ручнойspeedотказдосети. RealPG/CHRматрица3типовпрошла,0новыхdisabledсэмплов;HTTP/RBAC,16persistence tests иbuild passed. Runtime673e5ba не обновлён. Следующий12.5.17 — integratedPG-6 иdeployment; вся12.5 ещёоткрыта.
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
@@ -34,6 +34,18 @@
| 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.16 — выключенные серверы всех типов исключены из мониторинга (2026-10-07)
Аудит уточнилпричину12.5.15: uptime/RESTping намеренноиспользовалиenabled OR type=home-router, скомментариемобисключениидляLAN. Это существующееправило, непросто случайныйSQLдефект. Пользовательявновыбрал «Не опрашивать выключенные серверы любых типов». ПоэтомуисключениеHome Router удаленоосознанно, политикавключённоститеперьобщаядлявсехтипов.
НовыйlistEnabledMonitoringServers используетservers.enabled=true; подключёнкresources,scheduledping,manualpinggroup иRESTping. Плановыеspeed-пробы требуютвключённыхsource/destination ивключённойprobe; выключенныеendpointпропускаютсябезnativeoperation/ложногосэмплаошибки. Ручнойspeedguard проверяетобасерверапослечтенияизБД, доMikrotikClient/nativequeries, сявнойошибкой «Сервер отключён: включите его перед запуском теста». Уже начатыйдоотключениязапросможетштатнозавершиться; немедленнаяотменасетевойоперацииэтимнеобещается.
[RealPG/CHR evidence](ux-ui/acceptance/monitoring-enabled-2026-10-07.json): temporarycontainer/f3e2059+monitoringworktreepatch, mmapp_acceptance_20261007. Disabledserver3 последовательноимелтипыhome-router/exit-node/jump-host. Во всехслучаяхselected/resource IDs1–2, forwardednativeclients только1–2 (реальноечтениеresource/identity CHR, responses неподменены). Плановыепробы3→1/1→3 enabledtrue не запускались,runs0; manualspeed сdisabledsource/destination отказалдосозданияклиента. Повторныйзапускдобавилнезависимыйконтрольсэмплов: resourcecount3=1→1 (историческаяошибка12.5.15), RESTcount3=0→0, новыхсэмпловнет. Pingиспользуеттотжеqueryhelper,ноотдельныйnativepingfixtureвэтомблокенезапускался.
Временныеspeed probesудалены,server3 восстановленhome-router/enabledfalse, temporarycontainersудалены--rm. Рабочийстенд/source673e5ba/healthok инеизменённаяосновнаяБДсохранены. RouterOSконфигурациянеизменялась;толькоreadonlyresource/identity. SHA256compiledpatch совпалслокальным. Локальноspeed-test HTTP/RBAC (26invalidcases/401/403/dependencies),16speed-run-persistence tests,contracts/backend build иdiff-check прошли. Новыетривиальныемок-тестыSQLpredicate не добавлялись;поведениедоказано реальнойquery/collector матрицей.
Новыйкоднеразвёрнутнаосновномстенде. ПолныйintegratedPG-6,Portal/browserrestore ипрочие12.5 остаютсяоткрытыми. Следующий12.5.17 — integrated HTTP/scheduler/background/UDP quiescence иdeployment проверенногообраза. Локальныйкоммитбезpush.
## 12.5.15 — транзакционное восстановление разделов PostgreSQL (2026-10-07)
Исправленреальныйдефект12.5.14. pg_restore --list проверяетобязательныеTABLE public servers/schema_migrations иопределяетприсутствующиевархивеизвестныеpartition parents приложения. ВременныйSQL полностьюформируется pg_restore --clean --if-exists --file безподключениякцелевойБД. Затемодинpsql -X --single-transaction --set ON_ERROR_STOP=on выполняет -c parent constraint preparation и -f SQLархива. РодительскиеPK/UNIQUE снимаютсячерезpg_catalog/format(%I) внутриэтойжетрaнзакции; inheritedchildconstraints удаляютсякаскадно, поэтомупоследующиеIF EXISTS DROP больше непадают. Подготовкаограниченаpublic/известнымиparents, присутствующимивархиве; нетотдельногоcommittedDROP/SQLпереписыванияданных/автоповтора. [Транзакционныйрежимpsql](https://www.postgresql.org/docs/18/app-psql.html) охватываетобеопции-c/-f.
+13 -1
View File
@@ -1,6 +1,6 @@
# Этап 12: итоговая приёмка UX/UI
Актуальное продолжение 2026-10-07:12.5.15 завершён — транзакционный partition-safe restore исправлен и прошёл realAPI200/контрольархива/новыйID3; injected CREATE INDEX failure400 сохранилданные/sequence/1587constraints.25tests,HTTP/JWT иbuild passed. Основнойruntime673e5ba не обновлён. Следующий12.5.16 — disabled-server collector defect, integrated PG-6 иdeployment; весьэтап12.5 остаётсяоткрытым.
Актуальное продолжение 2026-10-07:12.5.16 завершён появномувыборупользователя — disabled исключаетвсетипыизuptime/RESTping/scheduledspeed; ручнойspeedотказдосети. RealPG/CHRматрица3типовпрошла,0новыхdisabledсэмплов;HTTP/RBAC,16persistence tests иbuild passed. Runtime673e5ba не обновлён. Следующий12.5.17 — integratedPG-6 иdeployment; вся12.5 ещёоткрыта.
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
@@ -1100,3 +1100,15 @@ Customdump иSQL содержатприватныеданные: tempdirectory07
[RealAPI evidence](ux-ui/acceptance/real-restore-fixed-2026-10-07.json):161.104.46.222/PG18.6, isolatedcompiledf1aac49+partition-restoreworktreepatch (SHA256 patch совпал), mmapp_acceptance_20261007. Backup200/475305bytes; concurrentactiveHTTPwrite ждалSQLlock, новыйGET409. Restore200/oktrueбезwarnings, контрольныеservers/retention/speed/migrations/sequence совпалисархивом. СледующийINSERT disabledtestserver192.0.2.250 получилID3. Послеretention19 ивведенияeventtrigger, которыйпадаетнаCREATE INDEX, второйrestore400/необъявленуспешным. НезависимыеSQLпослеrollback подтвердиливсеперечисленныеконтрольныеданные/sequence3 и1587constraint descriptors. Eventtrigger/function удалены, temporarycontainer--rm/consumers/pool штатноостановлены.
ПроверочнаяБД теперьсодержитdisabledserver3/retention19; основнаясохранена:server1–2,retention14,healthok/source673e5ba. Во времяштатногоrestart ресурсныйcollector неожиданнопыталсяпрочитатьdisabledserver3 иполучилtimeout10s — отдельныйдефектдляследующегоблока. RouterOS apply не выполнялся. PG-3/4 принятывграницахrealAPI/контрольныхданных/новогоID/SQLrollback/constraints, безполногоchecksum/Portal/browser UI. Integrated UDP+detachedjobs втомжекритическоминтервалеимультиэкземплярыещёнеприняты; полныйPG-6 открыт. Новыйкоднеразвёрнутнаосновномстенде. Следующий12.5.16 — исправитьdisabled-server polling, integratedPG-6/deployment. Локальныйкоммитбезpush.
## 12.5.16 — выключенные серверы всех типов исключены из мониторинга (2026-10-07)
Аудит уточнилпричину12.5.15: uptime/RESTping намеренноиспользовалиenabled OR type=home-router, скомментариемобисключениидляLAN. Это существующееправило, непросто случайныйSQLдефект. Пользовательявновыбрал «Не опрашивать выключенные серверы любых типов». ПоэтомуисключениеHome Router удаленоосознанно, политикавключённоститеперьобщаядлявсехтипов.
НовыйlistEnabledMonitoringServers используетservers.enabled=true; подключёнкresources,scheduledping,manualpinggroup иRESTping. Плановыеspeed-пробы требуютвключённыхsource/destination ивключённойprobe; выключенныеendpointпропускаютсябезnativeoperation/ложногосэмплаошибки. Ручнойspeedguard проверяетобасерверапослечтенияизБД, доMikrotikClient/nativequeries, сявнойошибкой «Сервер отключён: включите его перед запуском теста». Уже начатыйдоотключениязапросможетштатнозавершиться; немедленнаяотменасетевойоперацииэтимнеобещается.
[RealPG/CHR evidence](ux-ui/acceptance/monitoring-enabled-2026-10-07.json): temporarycontainer/f3e2059+monitoringworktreepatch, mmapp_acceptance_20261007. Disabledserver3 последовательноимелтипыhome-router/exit-node/jump-host. Во всехслучаяхselected/resource IDs1–2, forwardednativeclients только1–2 (реальноечтениеresource/identity CHR, responses неподменены). Плановыепробы3→1/1→3 enabledtrue не запускались,runs0; manualspeed сdisabledsource/destination отказалдосозданияклиента. Повторныйзапускдобавилнезависимыйконтрольсэмплов: resourcecount3=1→1 (историческаяошибка12.5.15), RESTcount3=0→0, новыхсэмпловнет. Pingиспользуеттотжеqueryhelper,ноотдельныйnativepingfixtureвэтомблокенезапускался.
Временныеspeed probesудалены,server3 восстановленhome-router/enabledfalse, temporarycontainersудалены--rm. Рабочийстенд/source673e5ba/healthok инеизменённаяосновнаяБДсохранены. RouterOSконфигурациянеизменялась;толькоreadonlyresource/identity. SHA256compiledpatch совпалслокальным. Локальноspeed-test HTTP/RBAC (26invalidcases/401/403/dependencies),16speed-run-persistence tests,contracts/backend build иdiff-check прошли. Новыетривиальныемок-тестыSQLpredicate не добавлялись;поведениедоказано реальнойquery/collector матрицей.
Новыйкоднеразвёрнутнаосновномстенде. ПолныйintegratedPG-6,Portal/browserrestore ипрочие12.5 остаютсяоткрытыми. Следующий12.5.17 — integrated HTTP/scheduler/background/UDP quiescence иdeployment проверенногообраза. Локальныйкоммитбезpush.
+4
View File
@@ -105,3 +105,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 root@161.104.46.222
## Partition-safe API restore — 2026-10-07
12.5.15:isolatedf1aac49+compiledpatch, [realAPIrestore200/новыйID3/injectedSQL400/rollback1587constraints](ux-ui/acceptance/real-restore-fixed-2026-10-07.json). ПроверочнаяБДmmapp_acceptance_20261007 содержитserver3 disabled192.0.2.250/retention19. ОсновнаяБДserver1–2/retention14/source673e5ba/healthok сохранена.25localtests,HTTP/JWT иbuild passed. Patchещёнеразвёрнут; следующий12.5.16 — disabled-server collector defect, integratedPG-6/deployment.
## Enabled-only мониторинг — 2026-10-07
По явномувыборупользователя12.5.16 исключаетdisabledвсетипыизuptime/RESTping/scheduledspeed, manualspeedпроверяетобасерверадосети. [Realматрица3типов/0новыхdisabledсэмплов](ux-ui/acceptance/monitoring-enabled-2026-10-07.json) прошла. ВпроверочнойБДserver3 сноваhome-router/enabledfalse, temporaryspeedprobesудалены. Основнойruntime673e5ba не обновлён,healthok. Следующий12.5.17 — integratedPG-6/deployment.
@@ -0,0 +1,100 @@
{
"date": "2026-10-07",
"source": "f3e2059+monitoring-enabled-worktree",
"database": "mmapp_acceptance_20261007",
"types": [
{
"type": "home-router",
"selectedServerIds": [
1,
2
],
"resourceServerIds": [
1,
2
],
"restJob": "servers_rest_ping",
"nativeClientServerIds": [
1,
2,
1,
2
],
"scheduledSpeedRuns": 0,
"manualDisabledSourceRejected": true,
"manualDisabledDestinationRejected": true
},
{
"type": "exit-node",
"selectedServerIds": [
1,
2
],
"resourceServerIds": [
1,
2
],
"restJob": "servers_rest_ping",
"nativeClientServerIds": [
1,
2,
1,
2
],
"scheduledSpeedRuns": 0,
"manualDisabledSourceRejected": true,
"manualDisabledDestinationRejected": true
},
{
"type": "jump-host",
"selectedServerIds": [
1,
2
],
"resourceServerIds": [
1,
2
],
"restJob": "servers_rest_ping",
"nativeClientServerIds": [
1,
2,
1,
2
],
"scheduledSpeedRuns": 0,
"manualDisabledSourceRejected": true,
"manualDisabledDestinationRejected": true
}
],
"mainDatabaseTouched": false,
"disabledSampleCountsBefore": {
"resource": 1,
"rest": 0
},
"disabledSampleCountsAfter": {
"resource": 1,
"rest": 0
},
"noNewDisabledSamples": true,
"limits": [
"In-flight calls admitted before disabling may finish",
"Read-only real resource/identity requests to CHR1/2; no RouterOS configuration changed",
"No full integrated PG-6 or main deployment in this block"
],
"patchSha256": "14422d2e40f6ab9ae6a9d0363163fc8036b5d3e59af7d43df24f3011c41fc0a4",
"policyApprovedByUser": "Do not poll disabled servers of any type",
"healthMainAfter": {
"status": "ok",
"timestamp": "2026-10-07T16:35:01.067Z",
"version": "1.0.0-test.673e5ba",
"eventLoopDelayMs": 20,
"flowWorker": {
"alive": false,
"bound": false,
"pendingSize": 0,
"dropped": 0,
"packetsReceived": 0
}
}
}