mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
add mysql, mariadb, postgresql, sqlite volumes support
This commit is contained in:
@@ -2,14 +2,16 @@ import { eq } from "drizzle-orm";
|
||||
import cron from "node-cron";
|
||||
import { CronExpressionParser } from "cron-parser";
|
||||
import { NotFoundError, BadRequestError, ConflictError } from "http-errors-enhanced";
|
||||
import * as fs from "node:fs/promises";
|
||||
import { db } from "../../db/db";
|
||||
import { backupSchedulesTable, repositoriesTable, volumesTable } from "../../db/schema";
|
||||
import { restic } from "../../utils/restic";
|
||||
import { logger } from "../../utils/logger";
|
||||
import { getVolumePath } from "../volumes/helpers";
|
||||
import { getVolumePath, isDatabaseVolume, getDumpFilePath } from "../volumes/helpers";
|
||||
import type { CreateBackupScheduleBody, UpdateBackupScheduleBody } from "./backups.dto";
|
||||
import { toMessage } from "../../utils/errors";
|
||||
import { serverEvents } from "../../core/events";
|
||||
import { executeDatabaseDump, type DatabaseConfig } from "../../utils/database-dump";
|
||||
|
||||
const runningBackups = new Map<number, AbortController>();
|
||||
|
||||
@@ -206,7 +208,28 @@ const executeBackup = async (scheduleId: number, manual = false) => {
|
||||
runningBackups.set(scheduleId, abortController);
|
||||
|
||||
try {
|
||||
const volumePath = getVolumePath(volume);
|
||||
let backupPath: string;
|
||||
let dumpFilePath: string | null = null;
|
||||
const isDatabase = isDatabaseVolume(volume);
|
||||
|
||||
if (isDatabase) {
|
||||
logger.info(`Creating database dump for volume ${volume.name}`);
|
||||
|
||||
const timestamp = Date.now();
|
||||
dumpFilePath = getDumpFilePath(volume, timestamp);
|
||||
|
||||
try {
|
||||
await executeDatabaseDump(volume.config as DatabaseConfig, dumpFilePath);
|
||||
logger.info(`Database dump created at: ${dumpFilePath}`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to create database dump: ${toMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
backupPath = dumpFilePath;
|
||||
} else {
|
||||
backupPath = getVolumePath(volume);
|
||||
}
|
||||
|
||||
const backupOptions: {
|
||||
exclude?: string[];
|
||||
@@ -226,7 +249,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
|
||||
backupOptions.include = schedule.includePatterns;
|
||||
}
|
||||
|
||||
await restic.backup(repository.config, volumePath, {
|
||||
await restic.backup(repository.config, backupPath, {
|
||||
...backupOptions,
|
||||
onProgress: (progress) => {
|
||||
serverEvents.emit("backup:progress", {
|
||||
@@ -242,6 +265,16 @@ const executeBackup = async (scheduleId: number, manual = false) => {
|
||||
await restic.forget(repository.config, schedule.retentionPolicy, { tag: schedule.id.toString() });
|
||||
}
|
||||
|
||||
// Clean up dump file if it was created
|
||||
if (dumpFilePath) {
|
||||
try {
|
||||
await fs.unlink(dumpFilePath);
|
||||
logger.info(`Cleaned up dump file: ${dumpFilePath}`);
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to clean up dump file: ${toMessage(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
const nextBackupAt = calculateNextRun(schedule.cronExpression);
|
||||
await db
|
||||
.update(backupSchedulesTable)
|
||||
|
||||
Reference in New Issue
Block a user