mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-15 00:15:17 +00:00
feat: extend volume backup functionality with scheduling and management
- Added support for volume backup jobs in the scheduling and removal processes. - Enhanced job management to include volume backups in the job queue. - Updated schema to accommodate volume backup data structure. - Implemented initialization of volume backup jobs based on server status, improving backup management.
This commit is contained in:
@@ -61,6 +61,12 @@ app.post("/update-backup", zValidator("json", jobQueueSchema), async (c) => {
|
|||||||
type: "schedule",
|
type: "schedule",
|
||||||
cronSchedule: job.pattern,
|
cronSchedule: job.pattern,
|
||||||
});
|
});
|
||||||
|
} else if (data.type === "volume-backup") {
|
||||||
|
result = await removeJob({
|
||||||
|
volumeBackupId: data.volumeBackupId,
|
||||||
|
type: "volume-backup",
|
||||||
|
cronSchedule: job.pattern,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
logger.info({ result }, "Job removed");
|
logger.info({ result }, "Job removed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ export const scheduleJob = (job: QueueJob) => {
|
|||||||
pattern: job.cronSchedule,
|
pattern: job.cronSchedule,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else if (job.type === "volume-backup") {
|
||||||
|
jobQueue.add(job.volumeBackupId, job, {
|
||||||
|
repeat: {
|
||||||
|
pattern: job.cronSchedule,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,6 +73,13 @@ export const removeJob = async (data: QueueJob) => {
|
|||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (data.type === "volume-backup") {
|
||||||
|
const { volumeBackupId, cronSchedule } = data;
|
||||||
|
const result = await jobQueue.removeRepeatable(volumeBackupId, {
|
||||||
|
pattern: cronSchedule,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,6 +102,10 @@ export const getJobRepeatable = async (
|
|||||||
const job = repeatableJobs.find((j) => j.name === scheduleId);
|
const job = repeatableJobs.find((j) => j.name === scheduleId);
|
||||||
return job ? job : null;
|
return job ? job : null;
|
||||||
}
|
}
|
||||||
|
if (data.type === "volume-backup") {
|
||||||
|
const { volumeBackupId } = data;
|
||||||
|
const job = repeatableJobs.find((j) => j.name === volumeBackupId);
|
||||||
|
return job ? job : null;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ export const jobQueueSchema = z.discriminatedUnion("type", [
|
|||||||
type: z.literal("schedule"),
|
type: z.literal("schedule"),
|
||||||
scheduleId: z.string(),
|
scheduleId: z.string(),
|
||||||
}),
|
}),
|
||||||
|
z.object({
|
||||||
|
cronSchedule: z.string(),
|
||||||
|
type: z.literal("volume-backup"),
|
||||||
|
volumeBackupId: z.string(),
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export type QueueJob = z.infer<typeof jobQueueSchema>;
|
export type QueueJob = z.infer<typeof jobQueueSchema>;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
findBackupById,
|
findBackupById,
|
||||||
findScheduleById,
|
findScheduleById,
|
||||||
findServerById,
|
findServerById,
|
||||||
|
findVolumeBackupById,
|
||||||
keepLatestNBackups,
|
keepLatestNBackups,
|
||||||
runCommand,
|
runCommand,
|
||||||
runComposeBackup,
|
runComposeBackup,
|
||||||
@@ -12,9 +13,15 @@ import {
|
|||||||
runMongoBackup,
|
runMongoBackup,
|
||||||
runMySqlBackup,
|
runMySqlBackup,
|
||||||
runPostgresBackup,
|
runPostgresBackup,
|
||||||
|
runVolumeBackup,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/dist/db";
|
import { db } from "@dokploy/server/dist/db";
|
||||||
import { backups, schedules, server } from "@dokploy/server/dist/db/schema";
|
import {
|
||||||
|
backups,
|
||||||
|
schedules,
|
||||||
|
server,
|
||||||
|
volumeBackups,
|
||||||
|
} from "@dokploy/server/dist/db/schema";
|
||||||
import { and, eq } from "drizzle-orm";
|
import { and, eq } from "drizzle-orm";
|
||||||
import { logger } from "./logger.js";
|
import { logger } from "./logger.js";
|
||||||
import { scheduleJob } from "./queue.js";
|
import { scheduleJob } from "./queue.js";
|
||||||
@@ -93,6 +100,12 @@ export const runJobs = async (job: QueueJob) => {
|
|||||||
if (schedule.enabled) {
|
if (schedule.enabled) {
|
||||||
await runCommand(schedule.scheduleId);
|
await runCommand(schedule.scheduleId);
|
||||||
}
|
}
|
||||||
|
} else if (job.type === "volume-backup") {
|
||||||
|
const { volumeBackupId } = job;
|
||||||
|
const volumeBackup = await findVolumeBackupById(volumeBackupId);
|
||||||
|
if (volumeBackup.enabled) {
|
||||||
|
await runVolumeBackup(volumeBackupId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
@@ -184,4 +197,44 @@ export const initializeJobs = async () => {
|
|||||||
{ Quantity: filteredSchedulesBasedOnServerStatus.length },
|
{ Quantity: filteredSchedulesBasedOnServerStatus.length },
|
||||||
"Schedules Initialized",
|
"Schedules Initialized",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const volumeBackupsResult = await db.query.volumeBackups.findMany({
|
||||||
|
where: eq(volumeBackups.enabled, true),
|
||||||
|
with: {
|
||||||
|
application: {
|
||||||
|
with: {
|
||||||
|
server: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
compose: {
|
||||||
|
with: {
|
||||||
|
server: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const filteredVolumeBackupsBasedOnServerStatus = volumeBackupsResult.filter(
|
||||||
|
(volumeBackup) => {
|
||||||
|
if (volumeBackup.application) {
|
||||||
|
return volumeBackup.application.server?.serverStatus === "active";
|
||||||
|
}
|
||||||
|
if (volumeBackup.compose) {
|
||||||
|
return volumeBackup.compose.server?.serverStatus === "active";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const volumeBackup of filteredVolumeBackupsBasedOnServerStatus) {
|
||||||
|
scheduleJob({
|
||||||
|
volumeBackupId: volumeBackup.volumeBackupId,
|
||||||
|
type: "volume-backup",
|
||||||
|
cronSchedule: volumeBackup.cronExpression,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
{ Quantity: filteredVolumeBackupsBasedOnServerStatus.length },
|
||||||
|
"Volume Backups Initialized",
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ export * from "./utils/notifications/utils";
|
|||||||
export * from "./utils/notifications/docker-cleanup";
|
export * from "./utils/notifications/docker-cleanup";
|
||||||
export * from "./utils/notifications/server-threshold";
|
export * from "./utils/notifications/server-threshold";
|
||||||
|
|
||||||
export * from "./utils/volume-backups/index";
|
|
||||||
|
|
||||||
export * from "./utils/builders/index";
|
export * from "./utils/builders/index";
|
||||||
export * from "./utils/builders/compose";
|
export * from "./utils/builders/compose";
|
||||||
export * from "./utils/builders/docker-file";
|
export * from "./utils/builders/docker-file";
|
||||||
@@ -135,5 +133,6 @@ export {
|
|||||||
|
|
||||||
export * from "./utils/schedules/utils";
|
export * from "./utils/schedules/utils";
|
||||||
export * from "./utils/schedules/index";
|
export * from "./utils/schedules/index";
|
||||||
|
export * from "./utils/volume-backups/index";
|
||||||
|
|
||||||
export * from "./lib/logger";
|
export * from "./lib/logger";
|
||||||
|
|||||||
Reference in New Issue
Block a user