fix(settings): сохранять результат операций базы при вторичных сбоях

This commit is contained in:
Denozordec committed 2026-10-03 16:43:52 +07:00
1 parent 738c98b9d3
commit 92b65a30ce
15 files changed
+159 -32

No files matched your search

+13 -15
View File
@@ -5,7 +5,9 @@ import os from "node:os"
import path from "node:path"
import { executeSystemDatabaseRestore, validateSystemDatabaseRestoreArchive, type SystemDatabaseRestoreOutcome } from "./system-database-restore-execution.js"
import { env } from "../config.js"
import { withAdvisoryLock } from "../db/index.js"
import { pool } from "../db/index.js"
import { withOperationLock } from "../db/operation-lock.js"
import { executeDatabaseOperation, type DatabaseOperationWarnings } from "./system-database-operation.js"
import { refreshScheduler, stopScheduler } from "./scheduler.js"
import {
startTrafficFlowListener,
@@ -34,7 +36,7 @@ function spawnCollected(command: string, args: string[], opts?: { stdin?: Buffer
child.on("error", reject)
child.on("close", (code) => {
if (code !== 0) {
reject(new Error(err.trim() || `${command} завершился с кодом ${code}`))
reject(new Error(err.trim().replaceAll(env.DATABASE_URL, "[DATABASE_URL]") || `${command} завершился с кодом ${code}`))
return
}
resolve(Buffer.concat(chunks))
@@ -44,20 +46,16 @@ function spawnCollected(command: string, args: string[], opts?: { stdin?: Buffer
})
}
async function withDatabaseOperation<T>(fn: () => Promise<T>): Promise<T> {
return await withAdvisoryLock(BACKUP_LOCK_KEY, async () => {
await stopTrafficFlowListener()
stopScheduler()
try {
return await fn()
} finally {
await startTrafficFlowListener()
await refreshScheduler()
}
})
async function withDatabaseOperation<T extends object>(fn: () => Promise<T>): Promise<T & DatabaseOperationWarnings> {
return withOperationLock(() => pool.connect(), BACKUP_LOCK_KEY, () => executeDatabaseOperation(fn, {
stopListener: stopTrafficFlowListener,
stopScheduler,
startListener: startTrafficFlowListener,
startScheduler: refreshScheduler,
}), "Операция с базой приложения уже выполняется")
}
export async function exportSystemDatabaseBackup(): Promise<{ filename: string; buffer: Buffer }> {
export async function exportSystemDatabaseBackup(): Promise<{ filename: string; buffer: Buffer } & DatabaseOperationWarnings> {
return await withDatabaseOperation(async () => {
const buffer = await spawnCollected("pg_dump", ["-Fc", env.DATABASE_URL])
return {
@@ -67,7 +65,7 @@ export async function exportSystemDatabaseBackup(): Promise<{ filename: string;
})
}
export async function restoreSystemDatabaseBackup(buffer: Buffer): Promise<SystemDatabaseRestoreOutcome> {
export async function restoreSystemDatabaseBackup(buffer: Buffer): Promise<SystemDatabaseRestoreOutcome & DatabaseOperationWarnings> {
validateSystemDatabaseRestoreArchive(buffer)
return await withDatabaseOperation(() => executeSystemDatabaseRestore(buffer, env.DATABASE_URL, {
allocate: async () => {