diff --git a/app/client/modules/backups/components/schedule-summary.tsx b/app/client/modules/backups/components/schedule-summary.tsx index 8bdd3b9d..87efda27 100644 --- a/app/client/modules/backups/components/schedule-summary.tsx +++ b/app/client/modules/backups/components/schedule-summary.tsx @@ -181,7 +181,8 @@ export const ScheduleSummary = (props: Props) => {

Warning Details

- Last backup completed with warnings. Check your container logs for more details. + {schedule.lastBackupError ?? + "Last backup completed with warnings. Check your container logs for more details."}

)} diff --git a/app/server/modules/backups/backups.service.ts b/app/server/modules/backups/backups.service.ts index f8dc2837..120dc7cc 100644 --- a/app/server/modules/backups/backups.service.ts +++ b/app/server/modules/backups/backups.service.ts @@ -431,23 +431,25 @@ const stopBackup = async (scheduleId: number) => { throw new NotFoundError("Backup schedule not found"); } - const abortController = runningBackups.get(scheduleId); - if (!abortController) { - throw new ConflictError("No backup is currently running for this schedule"); + try { + const abortController = runningBackups.get(scheduleId); + if (!abortController) { + throw new ConflictError("No backup is currently running for this schedule"); + } + + logger.info(`Stopping backup for schedule ${scheduleId}`); + + abortController.abort(); + } finally { + await db + .update(backupSchedulesTable) + .set({ + lastBackupStatus: "warning", + lastBackupError: "Backup was stopped by user", + updatedAt: Date.now(), + }) + .where(eq(backupSchedulesTable.id, scheduleId)); } - - logger.info(`Stopping backup for schedule ${scheduleId}`); - - abortController.abort(); - - await db - .update(backupSchedulesTable) - .set({ - lastBackupStatus: "warning", - lastBackupError: "Backup was stopped by user", - updatedAt: Date.now(), - }) - .where(eq(backupSchedulesTable.id, scheduleId)); }; const runForget = async (scheduleId: number, repositoryId?: string) => { diff --git a/app/server/modules/lifecycle/startup.ts b/app/server/modules/lifecycle/startup.ts index 2761bf88..1bf3265a 100644 --- a/app/server/modules/lifecycle/startup.ts +++ b/app/server/modules/lifecycle/startup.ts @@ -1,7 +1,7 @@ import { Scheduler } from "../../core/scheduler"; import { and, eq, or } from "drizzle-orm"; import { db } from "../../db/db"; -import { volumesTable } from "../../db/schema"; +import { backupSchedulesTable, volumesTable } from "../../db/schema"; import { logger } from "../../utils/logger"; import { restic } from "../../utils/restic"; import { volumeService } from "../volumes/volume.service"; @@ -63,6 +63,18 @@ export const startup = async () => { }); } + await db + .update(backupSchedulesTable) + .set({ + lastBackupStatus: "warning", + lastBackupError: "Zerobyte was restarted during the last scheduled backup", + updatedAt: Date.now(), + }) + .where(eq(backupSchedulesTable.lastBackupStatus, "in_progress")) + .catch((err) => { + logger.error(`Failed to update stuck backup schedules on startup: ${err.message}`); + }); + Scheduler.build(CleanupDanglingMountsJob).schedule("0 * * * *"); Scheduler.build(VolumeHealthCheckJob).schedule("*/30 * * * *"); Scheduler.build(RepositoryHealthCheckJob).schedule("50 12 * * *");