fix(api): сбросить кэши после восстановления базы
This commit is contained in:
1 parent
2943032462
commit
f1aac49dfc
18 files changed
+150
-17
No files matched your search
@@ -37,7 +37,7 @@
|
||||
"test:ospf-optimizer": "tsx src/services/ospf-optimizer-identity.test.ts && tsx src/services/ospf-optimizer-metrics.test.ts && tsx src/services/ospf-optimizer-plan.test.ts && tsx src/routes/ospf-optimizer.test.ts",
|
||||
"test:containers": "tsx src/services/containers-state.test.ts && tsx src/routes/containers-state.test.ts",
|
||||
"test:certificates": "tsx src/services/certificate-issue-execution.test.ts && tsx src/services/certificate-issue-request.test.ts && tsx src/routes/certificates-issue.test.ts && tsx src/services/certificate-issue-dto.test.ts && tsx src/services/certificate-parse.test.ts && tsx src/services/certificates-state.test.ts && tsx src/routes/certificates-state.test.ts",
|
||||
"test:system-database": "tsx src/services/database-background-work.test.ts && tsx src/services/database-request-gate.test.ts && tsx src/services/traffic-flow-worker-shutdown.test.ts && tsx src/services/system-database-restore-execution.test.ts && tsx src/services/system-database-operation.test.ts && tsx src/routes/system-database.test.ts && tsx src/plugins/auth.system-database.test.ts"
|
||||
"test:system-database": "tsx src/services/system-database-cache.test.ts && tsx src/services/database-background-work.test.ts && tsx src/services/database-request-gate.test.ts && tsx src/services/traffic-flow-worker-shutdown.test.ts && tsx src/services/system-database-restore-execution.test.ts && tsx src/services/system-database-operation.test.ts && tsx src/routes/system-database.test.ts && tsx src/plugins/auth.system-database.test.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.888.0",
|
||||
|
||||
@@ -10,6 +10,7 @@ import { withOperationLock } from "../db/operation-lock.js"
|
||||
import { executeDatabaseOperation, type DatabaseOperationWarnings } from "./system-database-operation.js"
|
||||
import { restartSchedulerAfterDatabaseOperation, stopSchedulerForDatabaseOperation } from "./scheduler.js"
|
||||
import { pauseRipeBackgroundWork, resumeRipeBackgroundWork } from "./traffic-flow-ripe.js"
|
||||
import { invalidateSystemDatabaseCaches } from "./system-database-cache.js"
|
||||
import {
|
||||
restartTrafficFlowListenerAfterDatabaseOperation,
|
||||
stopTrafficFlowListenerForDatabaseOperation,
|
||||
@@ -83,5 +84,6 @@ export async function restoreSystemDatabaseBackup(buffer: Buffer): Promise<Syste
|
||||
write: (file, data) => writeFile(file, data),
|
||||
run: async args => { await spawnCollected("pg_restore", args) },
|
||||
remove: file => rm(file, { force: true }),
|
||||
invalidate: invalidateSystemDatabaseCaches,
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { test } from "node:test"
|
||||
import { invalidateSystemDatabaseCaches } from "./system-database-cache.js"
|
||||
import { applyRingSnapshot, snapshotRings } from "./traffic-flow-engine.js"
|
||||
import { rememberServerIfaces, ifaceCacheHas } from "./traffic-flow-ifindex.js"
|
||||
import { DatabaseBackgroundWork } from "./database-background-work.js"
|
||||
import { executeDatabaseOperation } from "./system-database-operation.js"
|
||||
import { executeSystemDatabaseRestore } from "./system-database-restore-execution.js"
|
||||
import {
|
||||
disableRipePersistForTests, seedRipeCacheForTests, lookupRipeCached,
|
||||
pauseRipeBackgroundWork, resumeRipeBackgroundWork, enqueueRipeMisses, ripeFetchCountForTests,
|
||||
} from "./traffic-flow-ripe.js"
|
||||
|
||||
test("restore discards old RIPE, interface and live data without reopening RIPE admission", async () => {
|
||||
disableRipePersistForTests()
|
||||
seedRipeCacheForTests({ prefix: "8.8.8.0/24", asn: 15169, country: "US", lat: null, lng: null,
|
||||
holder: "old database", ok: true, fetchedAt: Date.now() })
|
||||
rememberServerIfaces(1, [{ ".id": "*1", name: "ether1" }])
|
||||
applyRingSnapshot([{ key: "old database", inBps: [1_000_000], outBps: [1_000_000] }])
|
||||
assert.equal(lookupRipeCached("8.8.8.8")?.holder, "old database")
|
||||
assert.equal(ifaceCacheHas(1), true)
|
||||
assert.equal(snapshotRings().length, 1)
|
||||
await pauseRipeBackgroundWork()
|
||||
try {
|
||||
const count = ripeFetchCountForTests()
|
||||
invalidateSystemDatabaseCaches()
|
||||
assert.equal(lookupRipeCached("8.8.8.8"), null)
|
||||
assert.equal(ifaceCacheHas(1), false)
|
||||
assert.equal(snapshotRings().length, 0)
|
||||
enqueueRipeMisses(["8.8.8.8"])
|
||||
assert.equal(ripeFetchCountForTests(), count)
|
||||
} finally { resumeRipeBackgroundWork() }
|
||||
})
|
||||
|
||||
test("background drain precedes restore and consumers restart with invalidated caches", async () => {
|
||||
const work = new DatabaseBackgroundWork(), calls: string[] = []
|
||||
let release!: () => void
|
||||
work.track(new Promise<void>(r => { release = r }))
|
||||
rememberServerIfaces(1, [{ ".id": "*1", name: "old-interface" }])
|
||||
const operation = executeDatabaseOperation(() => executeSystemDatabaseRestore(Buffer.from("PGDMPfixture"), "fixture", {
|
||||
allocate: async () => "fixture.dump", write: async () => {}, remove: async () => {},
|
||||
run: async () => { calls.push("restore") },
|
||||
invalidate: () => { calls.push("invalidate"); invalidateSystemDatabaseCaches() },
|
||||
}), {
|
||||
stopListener: () => { calls.push("stop listener") },
|
||||
stopScheduler: async () => { await work.drain(); calls.push("drained") },
|
||||
startListener: () => { assert.equal(ifaceCacheHas(1), false); calls.push("restart listener") },
|
||||
startScheduler: () => { calls.push("restart scheduler") },
|
||||
})
|
||||
await Promise.resolve(); await Promise.resolve()
|
||||
assert.equal(calls.includes("restore"), false)
|
||||
assert.equal(ifaceCacheHas(1), true)
|
||||
release(); await operation
|
||||
assert.deepEqual(calls, ["stop listener", "drained", "restore", "invalidate", "restart listener", "restart scheduler"])
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { invalidateTrafficFlowSettingsCache } from "./traffic-flow-settings.js"
|
||||
import { invalidateFlowCatalogCache } from "./traffic-flow-topology.js"
|
||||
import { invalidateRipeCache } from "./traffic-flow-ripe.js"
|
||||
import { invalidateIfaceCache } from "./traffic-flow-ifindex.js"
|
||||
import { invalidateFlowClassificationCache } from "./traffic-flow-classify.js"
|
||||
import { invalidateFlowAnalyticsCache } from "./traffic-flow-analytics.js"
|
||||
import { invalidateFlowMapHopsCache } from "./traffic-flow-map-hops.js"
|
||||
import { resetEngineAfterDatabaseRestore } from "./traffic-flow-engine.js"
|
||||
|
||||
/** Synchronous invalidation after confirmed restore and before consumers restart. */
|
||||
export function invalidateSystemDatabaseCaches(): void {
|
||||
invalidateTrafficFlowSettingsCache()
|
||||
invalidateFlowCatalogCache()
|
||||
invalidateRipeCache()
|
||||
invalidateIfaceCache()
|
||||
invalidateFlowClassificationCache()
|
||||
invalidateFlowAnalyticsCache()
|
||||
invalidateFlowMapHopsCache()
|
||||
resetEngineAfterDatabaseRestore()
|
||||
}
|
||||
@@ -7,3 +7,12 @@ test("invalid archive never allocates or runs command",async()=>{const f=fixture
|
||||
test("restore runs one transactional command and cleans file after success",async()=>{const f=fixture();assert.deepEqual(await executeSystemDatabaseRestore(dump,"postgres://fixture",f.deps),{});assert.deepEqual(f.calls,["allocate","write","run","remove"])})
|
||||
test("write or restore failure always cleans temporary file and never retries",async()=>{for(const step of ["write","run"]){const f=fixture();if(step==="write")f.setWrite();else f.setRun();await assert.rejects(executeSystemDatabaseRestore(dump,"postgres://fixture",f.deps),/failed/);assert.deepEqual(f.calls,step==="write"?["allocate","write","remove"]:["allocate","write","run","remove"])}})
|
||||
test("cleanup failure keeps confirmed restore result; main failure is preserved",async()=>{const f=fixture();f.setRemove();assert.deepEqual(await executeSystemDatabaseRestore(dump,"postgres://fixture",f.deps),{cleanupError:"Не удалось удалить временный файл восстановления"});const bad=fixture();bad.setRun();bad.setRemove();await assert.rejects(executeSystemDatabaseRestore(dump,"postgres://fixture",bad.deps),/restore failed; Не удалось удалить/)})
|
||||
|
||||
test("cache invalidation follows confirmed restore and is skipped on process failure", async () => {
|
||||
const success=fixture()
|
||||
await executeSystemDatabaseRestore(dump,"postgres://fixture",{...success.deps,invalidate:()=>{success.calls.push("invalidate")}})
|
||||
assert.deepEqual(success.calls,["allocate","write","run","invalidate","remove"])
|
||||
const failure=fixture();failure.setRun()
|
||||
await assert.rejects(executeSystemDatabaseRestore(dump,"postgres://fixture",{...failure.deps,invalidate:()=>{failure.calls.push("invalidate")}}),/restore failed/)
|
||||
assert.equal(failure.calls.includes("invalidate"),false)
|
||||
})
|
||||
@@ -4,6 +4,7 @@ interface Dependencies {
|
||||
write:(path:string,buffer:Buffer)=>Promise<void>
|
||||
run:(args:string[])=>Promise<void>
|
||||
remove:(path:string)=>Promise<void>
|
||||
invalidate?:()=>void
|
||||
}
|
||||
export function validateSystemDatabaseRestoreArchive(buffer:Buffer):void{
|
||||
if(buffer.length>512*1024*1024)throw new Error("Файл бэкапа слишком большой")
|
||||
@@ -16,6 +17,7 @@ export async function executeSystemDatabaseRestore(buffer:Buffer,databaseUrl:str
|
||||
try{
|
||||
await deps.write(file,buffer)
|
||||
await deps.run(["--single-transaction","--clean","--if-exists","-d",databaseUrl,file])
|
||||
deps.invalidate?.()
|
||||
}catch(error){failed=true;failure=error}
|
||||
finally{try{await deps.remove(file)}catch{cleanupError="Не удалось удалить временный файл восстановления"}}
|
||||
if(failed){const message=failure instanceof Error?failure.message:"Восстановление PostgreSQL не подтверждено";throw new Error(message+(cleanupError?"; "+cleanupError:""))}
|
||||
|
||||
@@ -152,7 +152,9 @@ export async function buildFlowAnalytics(q: FlowAnalyticsQuery): Promise<FlowAna
|
||||
return dto
|
||||
}
|
||||
|
||||
export function resetFlowAnalyticsCacheForTests(): void {
|
||||
export const resetFlowAnalyticsCacheForTests = invalidateFlowAnalyticsCache
|
||||
|
||||
export function invalidateFlowAnalyticsCache(): void {
|
||||
analyticsCache = null
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ export function disableCatalogFetchForTests(): void {
|
||||
catalogFetchEnabled = false
|
||||
}
|
||||
|
||||
export function resetFlowCatalogForTests(): void {
|
||||
export const resetFlowCatalogForTests = invalidateFlowClassificationCache
|
||||
|
||||
export function invalidateFlowClassificationCache(): void {
|
||||
cidrs = []
|
||||
asnPurpose = new Map()
|
||||
fetchedAt = 0
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
factsPendingSize,
|
||||
flushFlowFacts,
|
||||
hourBucketIso,
|
||||
resetFactsForTests,
|
||||
resetFactsAfterDatabaseRestore,
|
||||
} from "./traffic-flow-facts.js"
|
||||
|
||||
export const TICK_MS = 2_000
|
||||
@@ -1039,13 +1039,20 @@ export function ingestParsedFlowsForServerForTests(serverId: number, flows: Pars
|
||||
}
|
||||
|
||||
export function resetEngineForTests(): void {
|
||||
resetEngineAfterDatabaseRestore()
|
||||
pendingCap = MAX_PENDING
|
||||
}
|
||||
|
||||
/** Writers are drained before replacing the database; discard data from the old snapshot. */
|
||||
export function resetEngineAfterDatabaseRestore(): void {
|
||||
pending.clear()
|
||||
recent.clear()
|
||||
tickAccum.clear()
|
||||
rings.clear()
|
||||
minuteRollup.clear()
|
||||
minuteDims.clear()
|
||||
resetFactsForTests()
|
||||
resetFactsAfterDatabaseRestore()
|
||||
ensuredParts.clear()
|
||||
packetsReceived = 0
|
||||
lastExporterIp = null
|
||||
lastError = ""
|
||||
@@ -1060,7 +1067,6 @@ export function resetEngineForTests(): void {
|
||||
lastStatsPersistAt = 0
|
||||
lastPersistedStats = null
|
||||
bumpDataEpoch()
|
||||
pendingCap = MAX_PENDING
|
||||
}
|
||||
|
||||
export function pendingSizeForTests(): number {
|
||||
|
||||
@@ -270,7 +270,9 @@ export function factsPendingSize(): number {
|
||||
return hourFacts.size
|
||||
}
|
||||
|
||||
export function resetFactsForTests(): void {
|
||||
export const resetFactsForTests = resetFactsAfterDatabaseRestore
|
||||
|
||||
export function resetFactsAfterDatabaseRestore(): void {
|
||||
hourFacts.clear()
|
||||
ensuredParts.clear()
|
||||
}
|
||||
|
||||
@@ -187,7 +187,9 @@ export function markIfaceRefreshAttempt(serverId: number, at = Date.now()): void
|
||||
lastAttempt.set(serverId, at)
|
||||
}
|
||||
|
||||
export function resetIfaceCacheForTests(): void {
|
||||
export const resetIfaceCacheForTests = invalidateIfaceCache
|
||||
|
||||
export function invalidateIfaceCache(): void {
|
||||
cache.clear()
|
||||
fetchedAt.clear()
|
||||
lastAttempt.clear()
|
||||
|
||||
@@ -121,7 +121,9 @@ function bumpFrom(acc: DstAcc, exporterId: string, bytes: number, client: { user
|
||||
|
||||
let hopsCache: { key: string; at: number; dto: FlowMapHopsDto } | null = null
|
||||
|
||||
export function resetFlowMapHopsCacheForTests(): void {
|
||||
export const resetFlowMapHopsCacheForTests = invalidateFlowMapHopsCache
|
||||
|
||||
export function invalidateFlowMapHopsCache(): void {
|
||||
hopsCache = null
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,15 @@ export function disableRipeEnqueueForTests(): void {
|
||||
}
|
||||
|
||||
export function resetRipeCacheForTests(): void {
|
||||
invalidateRipeCache()
|
||||
workerRunning = false
|
||||
fetchCount = 0
|
||||
enqueueEnabled = true
|
||||
fetchImpl = globalThis.fetch.bind(globalThis)
|
||||
}
|
||||
|
||||
/** Call only after resolver/persistence drain; preserve pause and runtime options. */
|
||||
export function invalidateRipeCache(): void {
|
||||
mem.clear()
|
||||
asnHolder.clear()
|
||||
inflight.clear()
|
||||
@@ -68,10 +77,6 @@ export function resetRipeCacheForTests(): void {
|
||||
wideIndex.length = 0
|
||||
lastCandidateCount = 0
|
||||
loaded = persistEnabled ? false : true
|
||||
workerRunning = false
|
||||
fetchCount = 0
|
||||
enqueueEnabled = true
|
||||
fetchImpl = globalThis.fetch.bind(globalThis)
|
||||
}
|
||||
|
||||
export function seedRipeCacheForTests(entry: FlowIpMeta): void {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
Приложение использует 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.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; всяцепочка требуетintegrated quiescence12.5.13 иcache invalidation передrestore. Основнойстенд покаsource673e5ba. Другие экземпляры/хосты требуют отдельного контроля. PG-6 остаётся открытым до наблюдаемого подтверждения; восстановление стенда выполняется после его получения. Реальные тесты backend, способные очищать таблицы, запускаются только против выделенной тестовой БД.
|
||||
В локальном блоке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, способные очищать таблицы, запускаются только против выделенной тестовой БД.
|
||||
|
||||
После bootstrap достаточно следующих запросов чтения для начальной проверки, без вывода секретов:
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# План реализации UX/UI по пятичасовым окнам
|
||||
|
||||
Актуальное продолжение 2026-10-07:12.5.12 завершён локально — учтены detached backup jobs/audit, выпуск сертификатов, poll partition maintenance иbackground cache work; RIPE admission закрывается перед drain.19lifecycle/database tests,HTTP/JWT,backup/RIPE,10certificate tests иbuild passed. Основной runtime673e5ba не обновлён. Следующий12.5.13 — integrated HTTP/scheduler/background/UDP quiescence ввыделеннойБД, cache invalidation послеrestore иdeployment; PG-6/PG-3/4 ещёоткрыты.
|
||||
Актуальное продолжение 2026-10-07:12.5.13 завершён локально в части cache invalidation после подтверждённогоrestore. Проверен порядокbackground drain→restore→cache reset→consumer restart;22lifecycle/database tests,HTTP/JWT,RIPE/ifindex/classify иbuild passed. Runtime673e5ba не обновлён. Следующий12.5.14 — integrated real-PG quiescence/restore ввыделеннойБД иdeployment; PG-6/PG-3/4 ещёоткрыты.
|
||||
|
||||
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-07. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
|
||||
|
||||
|
||||
+11
-1
@@ -1,6 +1,6 @@
|
||||
# UX/UI: журнал реализации
|
||||
|
||||
Актуальное продолжение 2026-10-07:12.5.12 завершён локально — учтены detached backup jobs/audit, выпуск сертификатов, poll partition maintenance иbackground cache work; RIPE admission закрывается перед drain.19lifecycle/database tests,HTTP/JWT,backup/RIPE,10certificate tests иbuild passed. Основной runtime673e5ba не обновлён. Следующий12.5.13 — integrated HTTP/scheduler/background/UDP quiescence ввыделеннойБД, cache invalidation послеrestore иdeployment; PG-6/PG-3/4 ещёоткрыты.
|
||||
Актуальное продолжение 2026-10-07:12.5.13 завершён локально в части cache invalidation после подтверждённогоrestore. Проверен порядокbackground drain→restore→cache reset→consumer restart;22lifecycle/database tests,HTTP/JWT,RIPE/ifindex/classify иbuild passed. Runtime673e5ba не обновлён. Следующий12.5.14 — integrated real-PG quiescence/restore ввыделеннойБД иdeployment; PG-6/PG-3/4 ещёоткрыты.
|
||||
|
||||
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
|
||||
|
||||
@@ -34,6 +34,16 @@
|
||||
| 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.13 — сброс кэшей после подтверждённого восстановления БД (2026-10-07)
|
||||
|
||||
Добавлен invalidateSystemDatabaseCaches, вызываемый послеуспешногоpg_restore внутриrestore execution, доcleanup иперезапускаconsumers. Очищаются settingsRowCache, server/topology catalog, RIPE/index/ASN cache, интерфейсы, classification catalog, analytics/map hops, engine pending/recent/rings/minute accumulators иfact/engine ensured partition sets. Последнее исключаетповторноеиспользованиепамяткиосозданныхразделах, которыхуже можетнебытьввосстановленнойБД. Engine data epoch обновлён, runtime pending cap сохранён. GeoIP readers/file state не изменены: MMDB лежатвнеPostgreSQL dump.
|
||||
|
||||
Production invalidate/reset функции отделеныотForTests API; старыеимена сохраненыдлясуществующихтестов. RIPE invalidation сохраняетdatabase pause/enqueue/persist/fetch options: очисткакэшейне открывает admission воперации. Inflight tasks должныбытьпредварительнодренированы механизмами12.5.8–12; приошибкеpg_restore invalidation неприменяется.
|
||||
|
||||
Проверки: полныйtest:system-database21tests иHTTP/JWT scripts passed, затемновыйсовместныйcache/drain testpassed (всего22различныхtests). ПровереныудалениестарыхRIPE/interface/live данных безоткрытияRIPE, успешныйrestore→invalidate иотсутствиеinvalidate приошибкепроцесса. Совместныйfixtureснастоящимиoperation/restore helpers иbackground registry доказалпорядокstop listener→background drain→restore→invalidate→restart listener/scheduler; restart увиделочищенныйinterfacecache. Командаpg_restore вэтомfixture подмененаDI, это не реальныйPG-3. RIPE/ifindex/classify regression scripts иcontracts/backend build прошли; diff-check passed. БД/RouterOS влокальныхтестахнеизменялись.
|
||||
|
||||
Коднеразвёрнут: основнойruntime673e5ba сохраняется. PG-6 целикомоткрыт, чтение/rollback реальногоAPIrestore ещёнеподтверждено. PostgreSQL dump не содержитGeoIP/backup/certificate files; ихдоступностьнужноучитыватьвприёмке. Другиепроцессы/хосты gate/registry неостанавливает. Следующий12.5.14 — integrated real-PG HTTP/scheduler/background/UDP quiescence ввыделеннойпроверочнойБД, успешныйAPIrestore/ошибкапроцесса/sequence, затемdeploymentпроверенногообраза. Локальныйкоммитбезpush.
|
||||
|
||||
## 12.5.12 — ожидание фоновых jobs, audit и записей RIPE (2026-10-07)
|
||||
|
||||
Добавлен общий process-local DatabaseBackgroundWork. Promise регистрируется до запуска отложенного тела; drain ждёт settlement всех задач, включая дочерние записи, которые регистрируются во время завершения parent task. Timeout30сек отменяет database operation; pending registry сохраняется для следующего drain. Rejection наблюдается отдельно и не ломает ожидание остальных задач; завершение drain не объявляет неуспешные записи успешными.
|
||||
|
||||
+11
-1
@@ -1,6 +1,6 @@
|
||||
# Этап 12: итоговая приёмка UX/UI
|
||||
|
||||
Актуальное продолжение 2026-10-07:12.5.12 завершён локально — учтены detached backup jobs/audit, выпуск сертификатов, poll partition maintenance иbackground cache work; RIPE admission закрывается перед drain.19lifecycle/database tests,HTTP/JWT,backup/RIPE,10certificate tests иbuild passed. Основной runtime673e5ba не обновлён. Следующий12.5.13 — integrated HTTP/scheduler/background/UDP quiescence ввыделеннойБД, cache invalidation послеrestore иdeployment; PG-6/PG-3/4 ещёоткрыты.
|
||||
Актуальное продолжение 2026-10-07:12.5.13 завершён локально в части cache invalidation после подтверждённогоrestore. Проверен порядокbackground drain→restore→cache reset→consumer restart;22lifecycle/database tests,HTTP/JWT,RIPE/ifindex/classify иbuild passed. Runtime673e5ba не обновлён. Следующий12.5.14 — integrated real-PG quiescence/restore ввыделеннойБД иdeployment; PG-6/PG-3/4 ещёоткрыты.
|
||||
|
||||
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
|
||||
|
||||
@@ -1066,3 +1066,13 @@ RIPE учитывает loadPg, resolver worker иотдельные persist/per
|
||||
Проверки: test:system-database19pure/protocol tests иHTTP/JWT scripts passed (4background,4HTTPgate,4shutdown,4restore,3operation). Новый integration fixture среальнымbackup handler подтвердилHTTP202 иdrain, которыйне завершается доотложеннойcreate task. RIPE test сотключённымpersist иподменённымfetch подтвердил0fetch во времяpause ивозобновлениепослеresume. Существующийbackups-operations HTTP test passed;10certificate execution tests passed; contracts/backend build послеокончательныхизменений passed; diff-check passed. Тесты неочищалиБД инеприменялиRouterOS config.
|
||||
|
||||
Код пока неразвёрнут, основнойruntime673e5ba сохраняется; данные/CHR/auth стенданеизменялись. PG-6 остаётсяоткрытым доинтегрированногонаблюдения всехпутей. Restore ещёнепроверен; отдельнотребуется cache invalidation послевосстановления, иначеmemory topology/RIPE/settings могут отражатьпредыдущуюБД. Другиеэкземпляры/хосты registry негарантируетостанавливать. Следующий12.5.13 — integrated HTTP/scheduler/background/UDP quiescence ввыделеннойпроверочнойБД, аудитcache invalidation/deployment, затемPG-3/4. Локальныйкоммитбезpush.
|
||||
|
||||
## 12.5.13 — сброс кэшей после подтверждённого восстановления БД (2026-10-07)
|
||||
|
||||
Добавлен invalidateSystemDatabaseCaches, вызываемый послеуспешногоpg_restore внутриrestore execution, доcleanup иперезапускаconsumers. Очищаются settingsRowCache, server/topology catalog, RIPE/index/ASN cache, интерфейсы, classification catalog, analytics/map hops, engine pending/recent/rings/minute accumulators иfact/engine ensured partition sets. Последнее исключаетповторноеиспользованиепамяткиосозданныхразделах, которыхуже можетнебытьввосстановленнойБД. Engine data epoch обновлён, runtime pending cap сохранён. GeoIP readers/file state не изменены: MMDB лежатвнеPostgreSQL dump.
|
||||
|
||||
Production invalidate/reset функции отделеныотForTests API; старыеимена сохраненыдлясуществующихтестов. RIPE invalidation сохраняетdatabase pause/enqueue/persist/fetch options: очисткакэшейне открывает admission воперации. Inflight tasks должныбытьпредварительнодренированы механизмами12.5.8–12; приошибкеpg_restore invalidation неприменяется.
|
||||
|
||||
Проверки: полныйtest:system-database21tests иHTTP/JWT scripts passed, затемновыйсовместныйcache/drain testpassed (всего22различныхtests). ПровереныудалениестарыхRIPE/interface/live данных безоткрытияRIPE, успешныйrestore→invalidate иотсутствиеinvalidate приошибкепроцесса. Совместныйfixtureснастоящимиoperation/restore helpers иbackground registry доказалпорядокstop listener→background drain→restore→invalidate→restart listener/scheduler; restart увиделочищенныйinterfacecache. Командаpg_restore вэтомfixture подмененаDI, это не реальныйPG-3. RIPE/ifindex/classify regression scripts иcontracts/backend build прошли; diff-check passed. БД/RouterOS влокальныхтестахнеизменялись.
|
||||
|
||||
Коднеразвёрнут: основнойruntime673e5ba сохраняется. PG-6 целикомоткрыт, чтение/rollback реальногоAPIrestore ещёнеподтверждено. PostgreSQL dump не содержитGeoIP/backup/certificate files; ихдоступностьнужноучитыватьвприёмке. Другиепроцессы/хосты gate/registry неостанавливает. Следующий12.5.14 — integrated real-PG HTTP/scheduler/background/UDP quiescence ввыделеннойпроверочнойБД, успешныйAPIrestore/ошибкапроцесса/sequence, затемdeploymentпроверенногообраза. Локальныйкоммитбезpush.
|
||||
@@ -93,3 +93,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 [email protected]
|
||||
## Локальный detached work drain — 2026-10-07
|
||||
|
||||
12.5.12 добавляетучётbackground backup/audit/certificate/partition maintenance/cache work иpause RIPE enqueue сdrain текущихresolver/writes.19lifecycle/database tests,HTTP/JWT,backup/RIPE,10certificate tests иbuild прошли. На стенднеразвёрнуто; source673e5ba сохраняется. Следующий12.5.13 — integrated quiescence иcache invalidation передrestore/deployment. PG-6/3/4 остаютсяоткрытыми.
|
||||
|
||||
## Локальный cache invalidation patch — 2026-10-07
|
||||
|
||||
12.5.13 сбрасываетDB-зависимыеNetFlow caches/live buffers/partition memo послеуспешногоrestore доconsumer restart, сохраняяRIPE pause.22различныхlifecycle/database tests,HTTP/JWT,RIPE/ifindex/classify иbuild прошли. Runtime673e5ba не обновлён; следующий12.5.14 — integrated real-PG quiescence/restore ввыделеннойБД иdeployment. PG-6/3/4 остаютсяоткрытыми. Dump не включаетвнешниеbackup/certificate/MMDB files.
|
||||
Reference in new issue
Block a user