feature(backup): do not trigger retry on manual backup

This commit is contained in:
DerPenz 2026-04-10 14:59:53 +02:00 committed by Nico
parent 11bb95db92
commit 8765c5e705
2 changed files with 26 additions and 11 deletions

View file

@ -389,7 +389,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
const result = await validateBackupExecution(scheduleId, manual);
if (result.type !== "success") {
return handleValidationResult(scheduleId, result);
return handleValidationResult(scheduleId, result, manual);
}
const { context: ctx } = result;
@ -426,7 +426,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
switch (executionResult.status) {
case "unavailable":
return handleBackupFailure(scheduleId, ctx.organizationId, executionResult.error, ctx);
return handleBackupFailure(scheduleId, ctx.organizationId, executionResult.error, manual, ctx);
case "completed":
return finalizeSuccessfulBackup(
ctx,
@ -435,7 +435,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
executionResult.warningDetails,
);
case "failed":
return handleBackupFailure(scheduleId, ctx.organizationId, executionResult.error, ctx);
return handleBackupFailure(scheduleId, ctx.organizationId, executionResult.error, manual, ctx);
case "cancelled":
return handleBackupCancellation(scheduleId, ctx.organizationId, executionResult.message);
}
@ -447,7 +447,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
return;
}
return handleBackupFailure(scheduleId, ctx.organizationId, error, ctx);
return handleBackupFailure(scheduleId, ctx.organizationId, error, manual, ctx);
} finally {
backupExecutor.untrack(scheduleId, abortController);
cache.del(cacheKeys.backup.progress(scheduleId));

View file

@ -85,7 +85,11 @@ export async function validateBackupExecution(scheduleId: number, manual = false
};
}
export async function handleValidationResult(scheduleId: number, result: ValidationFailure | ValidationSkipped) {
export async function handleValidationResult(
scheduleId: number,
result: ValidationFailure | ValidationSkipped,
manual: boolean,
) {
const organizationId = getOrganizationId();
if (result.type === "skipped") {
@ -93,7 +97,7 @@ export async function handleValidationResult(scheduleId: number, result: Validat
return;
}
await handleBackupFailure(scheduleId, organizationId, result.error, result.partialContext);
await handleBackupFailure(scheduleId, organizationId, result.error, manual, result.partialContext);
}
export function emitBackupStarted(ctx: BackupContext, scheduleId: number) {
@ -205,6 +209,7 @@ export async function handleBackupFailure(
scheduleId: number,
organizationId: string,
error: unknown,
manual: boolean,
partialContext?: Partial<BackupContext>,
) {
const errorMessage = toMessage(error);
@ -228,7 +233,7 @@ export async function handleBackupFailure(
const nextRetryBackupAt = Date.now() + schedule.retryDelay;
const nextScheduledBackupAt = calculateNextRun(schedule.cronExpression);
if (shouldRetry && nextRetryBackupAt < nextScheduledBackupAt) {
if (!manual && shouldRetry && nextRetryBackupAt < nextScheduledBackupAt) {
await scheduleQueries.updateStatus(scheduleId, organizationId, {
lastBackupAt: Date.now(),
lastBackupStatus: "error",
@ -273,9 +278,15 @@ export async function handleBackupFailure(
const { volume, repository } = partialContext;
logger.error(
`Backup ${schedule.name} failed after ${maxRetries} retries for volume ${volume.name} to repository ${repository.name}: ${errorMessage}`,
);
if (manual) {
logger.error(
`Manual backup ${schedule.name} failed for volume ${volume.name} to repository ${repository.name}: ${errorMessage}`,
);
} else {
logger.error(
`Backup ${schedule.name} failed after ${maxRetries} retries for volume ${volume.name} to repository ${repository.name}: ${errorMessage}`,
);
}
serverEvents.emit("backup:completed", {
organizationId,
@ -285,12 +296,16 @@ export async function handleBackupFailure(
status: "error",
});
const errorNotificationMessage = manual
? `${errorDetails}`
: `${errorDetails}\n\nFailed after ${maxRetries} retry attempts.`;
notificationsService
.sendBackupNotification(scheduleId, "failure", {
volumeName: volume.name,
repositoryName: repository.name,
scheduleName: schedule.name,
error: `${errorDetails}\n\nFailed after ${maxRetries} retry attempts.`,
error: errorNotificationMessage,
})
.catch((notifyError) => {
logger.error(`Failed to send backup failure notification: ${toMessage(notifyError)}`);