fix(settings): восстанавливать базу транзакционно и сохранять результат операции
This commit is contained in:
1 parent
ff8b04bddf
commit
af5dbb0519
12 files changed
+86
-40
No files matched your search
@@ -0,0 +1,23 @@
|
||||
export type SystemDatabaseRestoreOutcome={cleanupError?:string}
|
||||
interface Dependencies {
|
||||
allocate:()=>Promise<string>
|
||||
write:(path:string,buffer:Buffer)=>Promise<void>
|
||||
run:(args:string[])=>Promise<void>
|
||||
remove:(path:string)=>Promise<void>
|
||||
}
|
||||
export function validateSystemDatabaseRestoreArchive(buffer:Buffer):void{
|
||||
if(buffer.length>512*1024*1024)throw new Error("Файл бэкапа слишком большой")
|
||||
if(buffer.length<5||!buffer.subarray(0,5).equals(Buffer.from("PGDMP")))throw new Error("Файл не похож на резервную копию PostgreSQL (PGDMP)")
|
||||
}
|
||||
export async function executeSystemDatabaseRestore(buffer:Buffer,databaseUrl:string,deps:Dependencies):Promise<SystemDatabaseRestoreOutcome>{
|
||||
validateSystemDatabaseRestoreArchive(buffer)
|
||||
const file=await deps.allocate()
|
||||
let failed=false,failure:unknown,cleanupError:string|undefined
|
||||
try{
|
||||
await deps.write(file,buffer)
|
||||
await deps.run(["--single-transaction","--clean","--if-exists","-d",databaseUrl,file])
|
||||
}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:""))}
|
||||
return cleanupError?{cleanupError}:{}
|
||||
}
|
||||
Reference in new issue
Block a user