fix(api): восстановить разделы PostgreSQL в одной транзакции

This commit is contained in:
Denozordec committed 2026-10-07 23:28:16 +07:00
1 parent c24ad7810c
commit f3e205950f
10 files changed
+261 -10

No files matched your search

+5 -1
View File
@@ -23,7 +23,7 @@
Реализация: [bootstrap](../backend/src/db/bootstrap.ts), [migrations](../backend/src/db/migrate.ts), [0008](../backend/drizzle/0008_alert_outbox_outcomes.sql), [0009](../backend/drizzle/0009_alert_outbox_resolution.sql), [database operation](../backend/src/services/system-database-operation.ts), [restore execution](../backend/src/services/system-database-restore-execution.ts).
Приложение использует pg_dump -Fc и pg_restore --single-transaction --clean --if-exists. Транзакционный режим описан в [документации PostgreSQL](https://www.postgresql.org/docs/current/app-pgrestore.html). Проверка пяти байтов PGDMP проверяет заголовок, но не полноту и не доверие к архиву. Для rollback нужен сценарий с ошибкой исполнения restore, а не только отказ HTTP до его начала.
После12.5.15 приложение используетpg_dump -Fc, проверкуpg_restore --list, генерациюpg_restore --clean --if-exists --file иодинpsql -X --single-transaction --set ON_ERROR_STOP=on -c partition parent preparation -f SQL. Предварительнаяподготовкаиrestore находятсявобщейтранзакции. Транзакционный режим описан в [документации PostgreSQL](https://www.postgresql.org/docs/current/app-pgrestore.html). Проверка пяти байтов PGDMP проверяет заголовок, но не полноту и не доверие к архиву. Для rollback нужен сценарий с ошибкой исполнения restore, а не только отказ HTTP до его начала.
В локальном блоке12.5.8 добавлено ожидание текущих scheduler jobs с закрытием admission, но этот код ещё не развёрнут на стенде673e5ba. Блок12.5.9 добавляет отдельный graceful shutdown worker для database operation, serial flush, pool.end и обязательные acknowledgement/exit0. Локальные protocol tests и настоящий isolated collector/UDP/blocked SQL drain12.5.10 прошли: [evidence](ux-ui/acceptance/netflow-worker-2026-10-07.json). Основной код на стенде ещё не обновлён; app-wide quiescence этим не подтверждена. Блок12.5.11 локально добавляет admission/drain всех API handlers иtraffic live streams; новые tests/build passed, на стенде patch не развёрнут. В12.5.12 локально добавлен общий background registry/drain дляbackup/audit/certificate/partition maintenance/cache work, атакжеpause RIPE enqueue. Tests/build passed; В12.5.13 добавленcache invalidation послеуспешногоrestore идоconsumer restart, локальныесовместныеhelpers tests passed. Всяцепочка требуетreal-PG integrated quiescence/restore12.5.14. Основнойстенд покаsource673e5ba. Другие экземпляры/хосты требуют отдельного контроля. PG-6 остаётся открытым до наблюдаемого подтверждения; восстановление стенда выполняется после его получения. Реальные тесты backend, способные очищать таблицы, запускаются только против выделенной тестовой БД.
@@ -93,3 +93,7 @@ BGP-prefix evaluator, отдельное live GRE расписание и recove
## Обнаруженный блокер restore — 2026-10-07
12.5.14 realAPI/sourcef1aac49 навыделеннойPG18.6 подтвердилadmission/drain,ноrestore400 из-заinheritedpartitionPRIMARY KEY при--clean. [Evidence/rollback controls](ux-ui/acceptance/real-restore-2026-10-07.json). PG-4 подтверждёнвграницахнастоящейSQLошибкииконтрольныхстрок/sequence/constraint; PG-3успех/последующийID иполныйPG-6 непроверены. Следующий12.5.15 исправляеттранзакционнуюочистку. Основнойruntime673e5ba сохранён.
## 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.
+1 -1
View File
@@ -1,6 +1,6 @@
# План реализации UX/UI по пятичасовым окнам
Актуальное продолжение 2026-10-07:12.5.14 выполненкакреальнаяприёмка isolated API/sourcef1aac49. ОбнаружендефектPG-3:pg_restore --clean падаетнаinherited partition PRIMARY KEY. HTTP admission409/ожиданиеwrite иrollback контрольныхданныхподтверждены. Основнойruntime673e5ba сохранён. Следующий12.5.15 — исправитьтранзакционнуюочисткуразделов иповторитьrestore; PG-3/полныйPG-6 открыты.
Актуальное продолжение 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 остаётсяоткрытым.
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-07. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
+13 -1
View File
@@ -1,6 +1,6 @@
# UX/UI: журнал реализации
Актуальное продолжение 2026-10-07:12.5.14 выполненкакреальнаяприёмка isolated API/sourcef1aac49. ОбнаружендефектPG-3:pg_restore --clean падаетнаinherited partition PRIMARY KEY. HTTP admission409/ожиданиеwrite иrollback контрольныхданныхподтверждены. Основнойruntime673e5ba сохранён. Следующий12.5.15 — исправитьтранзакционнуюочисткуразделов иповторитьrestore; PG-3/полныйPG-6 открыты.
Актуальное продолжение 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 остаётсяоткрытым.
Общий план: [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.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.
Customdump иSQL содержатприватныеданные: tempdirectory0700 (chmod такжеисправляетранее созданныйкаталог), файлы0600, обафайлаудаляютсяприуспехе/ошибке. Ошибкаdecode/неподходящийTOC непускаютtargetSQL. Архивдолженбытьдовереннымполнымbackup приложения; проверкадвухTABLE неявляетсяпроверкойвсейсхемыилидовериякSQLархива. CASCADEdependencies восстанавливаютсяизполногоархива; частичные/custom archives этимнепринимались.
Локальныепроверки:3новыхpartition-restoretests включенывtest:system-database; полныйнабор25pure/protocol tests иHTTP/JWT scripts passed, contracts/backend build passed. Провереныscope parent/table/schema, quotedcatalogidentifiers, полностьюdecode-before-targetSQL, одинpsqltransaction, отказdecodeбезtargetSQL. Существующийrestore lifecycle сохраняетcache invalidation толькопослеуспеха.
[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.14 — реальный API restore: дефект очистки разделов и контроль rollback (2026-10-07)
Временный docker compose run --rm --no-deps backend использовалcompiled dist sourcef1aac49, mount/app/backend/acceptance, DATABASE_URL толькоmmapp_acceptance_20261007, HTTP127.0.0.1:8014 внутриконтейнера. Основнойbackend/frontend не обновлялись. [Очищенный отчёт](ux-ui/acceptance/real-restore-2026-10-07.json); SHA256 переданногоcompiled archive совпалслокальным. РеальныйbuildApp иAPI routes работалибезHTTP mocks; startScheduler=false приinitial build, стандартныеdatabase operation restarts выполнялиреальныйrefreshScheduler/consumer lifecycle.
+13 -1
View File
@@ -1,6 +1,6 @@
# Этап 12: итоговая приёмка UX/UI
Актуальное продолжение 2026-10-07:12.5.14 выполненкакреальнаяприёмка isolated API/sourcef1aac49. ОбнаружендефектPG-3:pg_restore --clean падаетнаinherited partition PRIMARY KEY. HTTP admission409/ожиданиеwrite иrollback контрольныхданныхподтверждены. Основнойruntime673e5ba сохранён. Следующий12.5.15 — исправитьтранзакционнуюочисткуразделов иповторитьrestore; PG-3/полныйPG-6 открыты.
Актуальное продолжение 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 остаётсяоткрытым.
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
@@ -1088,3 +1088,15 @@ GETbackup200/478810bytes/PGDMP полученвпамять безкопиров
Изолированныйконтейнерудалён--rm,егоscheduler/background/worker остановлены,соединениязакрыты. ПроверочнаяБД теперьretention16; основнойстендпо-прежнемуretention14,обаCHRзаписи сохранены,healthok/version1.0.0-test.673e5ba. Nativegre/BGP collector можетвыполнятьчтениеприштатномrestart,ноRouterOS apply/конфигурациянеизменялись. РеальныйPortal/browser restore UI иintegrated UDP+detached jobs втомжекритическоминтервалеэтимнепроверены.
Обнаруженныйдефектблокируетуспешнуюприёмкуrestore; коднеразвёрнутвосновномприложении. Следующий12.5.15 — исправитьочисткуpartition constraints внутриоднойтранзакции, безпредварительногонеобратимогоDROP ибезавтоматическогоповторапосленеизвестногоcommit, затемповторитьPG-3/4/полныйPG-6. Локальныйкоммитбез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.
Customdump иSQL содержатприватныеданные: tempdirectory0700 (chmod такжеисправляетранее созданныйкаталог), файлы0600, обафайлаудаляютсяприуспехе/ошибке. Ошибкаdecode/неподходящийTOC непускаютtargetSQL. Архивдолженбытьдовереннымполнымbackup приложения; проверкадвухTABLE неявляетсяпроверкойвсейсхемыилидовериякSQLархива. CASCADEdependencies восстанавливаютсяизполногоархива; частичные/custom archives этимнепринимались.
Локальныепроверки:3новыхpartition-restoretests включенывtest:system-database; полныйнабор25pure/protocol tests иHTTP/JWT scripts passed, contracts/backend build passed. Провереныscope parent/table/schema, quotedcatalogidentifiers, полностьюdecode-before-targetSQL, одинpsqltransaction, отказdecodeбезtargetSQL. Существующийrestore lifecycle сохраняетcache invalidation толькопослеуспеха.
[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.
+4
View File
@@ -101,3 +101,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 [email protected]
## Реальный API restore failure — 2026-10-07
[12.5.14 evidence](ux-ui/acceptance/real-restore-2026-10-07.json): isolatedsourcef1aac49/API againstmmapp_acceptance_20261007, backup200, activewrite drain/GET409. Restore400:inheritedpartitionPK нельзяудалитьсуществующим--clean. Контрольrollback прошёл (servers/speed/migrations/sequence/retention16/constraint). ПроверочнаяБДretention16,основнаяretention14/source673e5ba/healthok сохранены. Runtimeнеобновлён,PG-3 иполныйPG-6 открыты. Следующий12.5.15 — транзакционноеисправлениеclean иповторнаяприёмка.
## 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.
@@ -0,0 +1,118 @@
{
"date": "2026-10-07",
"source": "f1aac49+partition-restore-worktree",
"database": "mmapp_acceptance_20261007",
"mode": "real HTTP API against isolated PostgreSQL",
"mainDatabaseTouched": false,
"backup": {
"status": 200,
"bytes": 475305
},
"admission": {
"blockedGet": 409,
"waitedForActiveWrite": true
},
"restore": {
"status": 200,
"outcome": {
"ok": true
}
},
"controlsMatch": true,
"nextServerId": 3,
"failedRestore": {
"status": 400,
"expectedSqlFailure": true,
"reportedSuccess": false
},
"rollbackControlsMatch": true,
"constraintsMatch": true,
"constraintCount": 1587,
"controlsAfterFailure": {
"servers": [
{
"id": 1,
"host": "194.226.121.150",
"enabled": true
},
{
"id": 2,
"host": "104.165.244.7",
"enabled": true
},
{
"id": 3,
"host": "192.0.2.250",
"enabled": false
}
],
"uptime": [
{
"id": 1,
"retention_days": 19
}
],
"speed": [
{
"count": 5
}
],
"sequence": [
{
"last_value": 3,
"is_called": true
}
],
"migrations": [
{
"id": "0000_postgresql"
},
{
"id": "0002_compact_schema"
},
{
"id": "0003_backup_s3"
},
{
"id": "0004_geoip_settings"
},
{
"id": "0005_flow_facts"
},
{
"id": "0006_config_revisions"
},
{
"id": "0007_flow_buckets_nat"
},
{
"id": "0008_alert_outbox_outcomes"
},
{
"id": "0009_alert_outbox_resolution"
}
]
},
"limits": [
"One isolated backend instance; no cross-host quiescence proof",
"Integrated UDP and detached jobs in same critical interval not injected",
"No Portal SSO or browser restore UI tested",
"Main runtime remains673e5ba; isolated f1aac49 plus compiled patch tested",
"Restart resource collector attempted disabled server3 at192.0.2.250 and timed out; separate defect to investigate"
],
"patchSha256": "19fca8bb99b1b7051224078a554562abacf35feebe0ff918756e082adc9dcaee",
"restoreMethod": "pg_restore --list, pg_restore --clean --if-exists --file, psql -X --single-transaction --set ON_ERROR_STOP=on -c parent preparation -f generated SQL",
"healthMainAfter": {
"status": "ok",
"timestamp": "2026-10-07T16:26:19.859Z",
"version": "1.0.0-test.673e5ba",
"eventLoopDelayMs": 20,
"flowWorker": {
"alive": false,
"bound": false,
"pendingSize": 0,
"dropped": 0,
"packetsReceived": 0
}
}
}