Implement restore functionality for various database types

- Added `apiRestoreBackup` schema to define input requirements for restore operations.
- Refactored restore utilities for PostgreSQL, MySQL, MariaDB, and MongoDB to utilize a unified command generation approach, enhancing maintainability.
- Improved logging during restore processes to provide clearer feedback on command execution and success/failure states.
- Streamlined the handling of database credentials and backup file paths across different database types, ensuring consistency and reducing redundancy.
This commit is contained in:
Mauricio Siu
2025-05-04 03:25:58 -06:00
parent 66dd890448
commit 614b9d25a8
9 changed files with 295 additions and 207 deletions
+18 -20
View File
@@ -1,15 +1,15 @@
import type { Destination } from "@dokploy/server/services/destination";
import type { Postgres } from "@dokploy/server/services/postgres";
import { getS3Credentials } from "../backups/utils";
import { getServiceContainer } from "../docker/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getPostgresRestoreCommand } from "./utils";
import { getRestoreCommand } from "./utils";
import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { z } from "zod";
export const restorePostgresBackup = async (
postgres: Postgres,
destination: Destination,
database: string,
backupFile: string,
backupInput: z.infer<typeof apiRestoreBackup>,
emit: (log: string) => void,
) => {
try {
@@ -18,32 +18,30 @@ export const restorePostgresBackup = async (
const rcloneFlags = getS3Credentials(destination);
const bucketPath = `:s3:${destination.bucket}`;
const backupPath = `${bucketPath}/${backupFile}`;
const backupPath = `${bucketPath}/${backupInput.backupFile}`;
const { Id: containerId } = await getServiceContainer(appName, serverId);
const rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip`;
emit("Starting restore...");
emit(`Backup path: ${backupPath}`);
const restoreCommand = getPostgresRestoreCommand(
containerId,
database,
databaseUser,
);
const command = `\
rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip | ${restoreCommand}`;
const command = getRestoreCommand({
appName,
credentials: {
database: backupInput.databaseName,
databaseUser,
},
type: "postgres",
rcloneCommand,
restoreType: "database",
});
emit(`Executing command: ${command}`);
if (serverId) {
const { stdout, stderr } = await execAsyncRemote(serverId, command);
emit(stdout);
emit(stderr);
await execAsyncRemote(serverId, command);
} else {
const { stdout, stderr } = await execAsync(command);
emit(stdout);
emit(stderr);
await execAsync(command);
}
emit("Restore completed successfully!");