fix: remove cron jobs after delete service

This commit is contained in:
Mauricio Siu
2025-01-26 18:59:27 -06:00
parent 1e56364f93
commit 0fb67ced5d
8 changed files with 72 additions and 8 deletions

View File

@@ -89,7 +89,7 @@ const mySchema = z.discriminatedUnion("type", [
z z
.object({ .object({
type: z.literal("postgres"), type: z.literal("postgres"),
databaseName: z.string().min(1, "Database name required"), databaseName: z.string().default("postgres"),
databaseUser: z.string().default("postgres"), databaseUser: z.string().default("postgres"),
}) })
.merge(baseDatabaseSchema), .merge(baseDatabaseSchema),
@@ -110,7 +110,10 @@ const mySchema = z.discriminatedUnion("type", [
type: z.literal("mysql"), type: z.literal("mysql"),
databaseRootPassword: z.string().default(""), databaseRootPassword: z.string().default(""),
databaseUser: z.string().default("mysql"), databaseUser: z.string().default("mysql"),
databaseName: z.string().min(1, "Database name required"), databaseName: z
.string()
.min(1, "Database name required")
.default("mysql"),
}) })
.merge(baseDatabaseSchema), .merge(baseDatabaseSchema),
z z
@@ -119,7 +122,10 @@ const mySchema = z.discriminatedUnion("type", [
dockerImage: z.string().default("mariadb:4"), dockerImage: z.string().default("mariadb:4"),
databaseRootPassword: z.string().default(""), databaseRootPassword: z.string().default(""),
databaseUser: z.string().default("mariadb"), databaseUser: z.string().default("mariadb"),
databaseName: z.string().min(1, "Database name required"), databaseName: z
.string()
.min(1, "Database name required")
.default("mariadb"),
}) })
.merge(baseDatabaseSchema), .merge(baseDatabaseSchema),
]); ]);
@@ -206,7 +212,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
promise = postgresMutation.mutateAsync({ promise = postgresMutation.mutateAsync({
...commonParams, ...commonParams,
databasePassword: data.databasePassword, databasePassword: data.databasePassword,
databaseName: data.databaseName, databaseName: data.databaseName || "postgres",
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
@@ -233,7 +239,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
...commonParams, ...commonParams,
databasePassword: data.databasePassword, databasePassword: data.databasePassword,
databaseRootPassword: data.databaseRootPassword, databaseRootPassword: data.databaseRootPassword,
databaseName: data.databaseName, databaseName: data.databaseName || "mariadb",
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
serverId: data.serverId, serverId: data.serverId,
@@ -242,7 +248,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
promise = mysqlMutation.mutateAsync({ promise = mysqlMutation.mutateAsync({
...commonParams, ...commonParams,
databasePassword: data.databasePassword, databasePassword: data.databasePassword,
databaseName: data.databaseName, databaseName: data.databaseName || "mysql",
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
databaseRootPassword: data.databaseRootPassword, databaseRootPassword: data.databaseRootPassword,

View File

@@ -9,6 +9,7 @@ import {
apiSaveExternalPortMariaDB, apiSaveExternalPortMariaDB,
apiUpdateMariaDB, apiUpdateMariaDB,
} from "@/server/db/schema"; } from "@/server/db/schema";
import { cancelJobs } from "@/server/utils/backup";
import { import {
IS_CLOUD, IS_CLOUD,
addNewService, addNewService,
@@ -16,6 +17,7 @@ import {
createMariadb, createMariadb,
createMount, createMount,
deployMariadb, deployMariadb,
findBackupsByDbId,
findMariadbById, findMariadbById,
findProjectById, findProjectById,
findServerById, findServerById,
@@ -211,8 +213,10 @@ export const mariadbRouter = createTRPCRouter({
}); });
} }
const backups = await findBackupsByDbId(input.mariadbId, "mariadb");
const cleanupOperations = [ const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId), async () => await removeService(mongo?.appName, mongo.serverId),
async () => await cancelJobs(backups),
async () => await removeMariadbById(input.mariadbId), async () => await removeMariadbById(input.mariadbId),
]; ];

View File

@@ -9,6 +9,7 @@ import {
apiSaveExternalPortMongo, apiSaveExternalPortMongo,
apiUpdateMongo, apiUpdateMongo,
} from "@/server/db/schema"; } from "@/server/db/schema";
import { cancelJobs } from "@/server/utils/backup";
import { import {
IS_CLOUD, IS_CLOUD,
addNewService, addNewService,
@@ -16,6 +17,7 @@ import {
createMongo, createMongo,
createMount, createMount,
deployMongo, deployMongo,
findBackupsByDbId,
findMongoById, findMongoById,
findProjectById, findProjectById,
removeMongoById, removeMongoById,
@@ -252,9 +254,11 @@ export const mongoRouter = createTRPCRouter({
message: "You are not authorized to delete this mongo", message: "You are not authorized to delete this mongo",
}); });
} }
const backups = await findBackupsByDbId(input.mongoId, "mongo");
const cleanupOperations = [ const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId), async () => await removeService(mongo?.appName, mongo.serverId),
async () => await cancelJobs(backups),
async () => await removeMongoById(input.mongoId), async () => await removeMongoById(input.mongoId),
]; ];

View File

@@ -19,6 +19,7 @@ import {
createMount, createMount,
createMysql, createMysql,
deployMySql, deployMySql,
findBackupsByDbId,
findMySqlById, findMySqlById,
findProjectById, findProjectById,
removeMySqlById, removeMySqlById,
@@ -30,6 +31,7 @@ import {
updateMySqlById, updateMySqlById,
} from "@dokploy/server"; } from "@dokploy/server";
import { observable } from "@trpc/server/observable"; import { observable } from "@trpc/server/observable";
import { cancelJobs } from "@/server/utils/backup";
export const mysqlRouter = createTRPCRouter({ export const mysqlRouter = createTRPCRouter({
create: protectedProcedure create: protectedProcedure
@@ -249,8 +251,10 @@ export const mysqlRouter = createTRPCRouter({
}); });
} }
const backups = await findBackupsByDbId(input.mysqlId, "mysql");
const cleanupOperations = [ const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId), async () => await removeService(mongo?.appName, mongo.serverId),
async () => await cancelJobs(backups),
async () => await removeMySqlById(input.mysqlId), async () => await removeMySqlById(input.mysqlId),
]; ];

View File

@@ -21,6 +21,7 @@ import {
createMount, createMount,
createPostgres, createPostgres,
deployPostgres, deployPostgres,
findBackupsByDbId,
findPostgresById, findPostgresById,
findProjectById, findProjectById,
removePostgresById, removePostgresById,
@@ -34,6 +35,7 @@ import {
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { observable } from "@trpc/server/observable"; import { observable } from "@trpc/server/observable";
import { z } from "zod"; import { z } from "zod";
import { cancelJobs } from "@/server/utils/backup";
const ee = new EventEmitter(); const ee = new EventEmitter();
@@ -231,8 +233,11 @@ export const postgresRouter = createTRPCRouter({
}); });
} }
const backups = await findBackupsByDbId(input.postgresId, "postgres");
const cleanupOperations = [ const cleanupOperations = [
removeService(postgres.appName, postgres.serverId), removeService(postgres.appName, postgres.serverId),
cancelJobs(backups),
removePostgresById(input.postgresId), removePostgresById(input.postgresId),
]; ];

View File

@@ -244,7 +244,6 @@ export const redisRouter = createTRPCRouter({
message: "You are not authorized to delete this Redis", message: "You are not authorized to delete this Redis",
}); });
} }
const cleanupOperations = [ const cleanupOperations = [
async () => await removeService(redis?.appName, redis.serverId), async () => await removeService(redis?.appName, redis.serverId),
async () => await removeRedisById(input.redisId), async () => await removeRedisById(input.redisId),

View File

@@ -1,3 +1,10 @@
import {
type BackupScheduleList,
IS_CLOUD,
removeScheduleBackup,
scheduleBackup,
} from "@dokploy/server/index";
type QueueJob = type QueueJob =
| { | {
type: "backup"; type: "backup";
@@ -59,3 +66,19 @@ export const updateJob = async (job: QueueJob) => {
throw error; throw error;
} }
}; };
export const cancelJobs = async (backups: BackupScheduleList) => {
for (const backup of backups) {
if (backup.enabled) {
if (IS_CLOUD) {
await removeJob({
cronSchedule: backup.schedule,
backupId: backup.backupId,
type: "backup",
});
} else {
removeScheduleBackup(backup.backupId);
}
}
}
};

View File

@@ -2,11 +2,13 @@ import { db } from "@dokploy/server/db";
import { type apiCreateBackup, backups } from "@dokploy/server/db/schema"; import { type apiCreateBackup, backups } from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { IS_CLOUD } from "../constants";
import { removeScheduleBackup, scheduleBackup } from "../utils/backups/utils";
export type Backup = typeof backups.$inferSelect; export type Backup = typeof backups.$inferSelect;
export type BackupSchedule = Awaited<ReturnType<typeof findBackupById>>; export type BackupSchedule = Awaited<ReturnType<typeof findBackupById>>;
export type BackupScheduleList = Awaited<ReturnType<typeof findBackupsByDbId>>;
export const createBackup = async (input: typeof apiCreateBackup._type) => { export const createBackup = async (input: typeof apiCreateBackup._type) => {
const newBackup = await db const newBackup = await db
.insert(backups) .insert(backups)
@@ -69,3 +71,20 @@ export const removeBackupById = async (backupId: string) => {
return result[0]; return result[0];
}; };
export const findBackupsByDbId = async (
id: string,
type: "postgres" | "mysql" | "mariadb" | "mongo",
) => {
const result = await db.query.backups.findMany({
where: eq(backups[`${type}Id`], id),
with: {
postgres: true,
mysql: true,
mariadb: true,
mongo: true,
destination: true,
},
});
return result || [];
};