26 lines
1.5 KiB
TypeScript
26 lines
1.5 KiB
TypeScript
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>
|
|
invalidate?:()=>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])
|
|
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:""))}
|
|
return cleanupError?{cleanupError}:{}
|
|
}
|