fix(backup): keep old path when agent is disabled

This commit is contained in:
Nicolas Meienberger 2026-04-12 16:48:51 +02:00
parent 38b4ac2c5c
commit d5eea2fb97
No known key found for this signature in database

View file

@ -1,10 +1,13 @@
import { Effect } from "effect";
import type { BackupSchedule, Volume, Repository } from "../../db/schema"; import type { BackupSchedule, Volume, Repository } from "../../db/schema";
import { resticDeps } from "../../core/restic"; import { config } from "../../core/config";
import { restic, resticDeps } from "../../core/restic";
import type { BackupRunPayload } from "@zerobyte/contracts/agent-protocol"; import type { BackupRunPayload } from "@zerobyte/contracts/agent-protocol";
import { agentManager, type BackupExecutionProgress } from "../agents/agents-manager"; import { agentManager, type BackupExecutionProgress } from "../agents/agents-manager";
import { getVolumePath } from "../volumes/helpers"; import { getVolumePath } from "../volumes/helpers";
import { decryptRepositoryConfig } from "../repositories/repository-config-secrets"; import { decryptRepositoryConfig } from "../repositories/repository-config-secrets";
import { createBackupOptions } from "./backup.helpers"; import { createBackupOptions } from "./backup.helpers";
import { toErrorDetails } from "../../utils/errors";
const LOCAL_AGENT_ID = "local"; const LOCAL_AGENT_ID = "local";
@ -56,6 +59,47 @@ const createBackupRunPayload = async ({
}; };
}; };
const executeBackupWithoutAgent = async (
payload: BackupRunPayload,
{ signal, onProgress }: Pick<BackupExecutionRequest, "signal" | "onProgress">,
) => {
try {
const execution = await Effect.runPromise(
restic
.backup(payload.repositoryConfig, payload.sourcePath, {
...payload.options,
organizationId: payload.organizationId,
signal,
onProgress,
})
.pipe(
Effect.map((result) => ({ success: true as const, result })),
Effect.catchAll((error) => Effect.succeed({ success: false as const, error })),
),
);
if (!execution.success) {
return {
status: "failed" as const,
error: toErrorDetails(execution.error),
};
}
const { exitCode, result, warningDetails } = execution.result;
return {
status: "completed" as const,
exitCode,
result,
warningDetails,
};
} catch (error) {
return {
status: "failed" as const,
error: toErrorDetails(error),
};
}
};
export const backupExecutor = { export const backupExecutor = {
track: (scheduleId: number) => { track: (scheduleId: number) => {
const abortController = new AbortController(); const abortController = new AbortController();
@ -73,23 +117,30 @@ export const backupExecutor = {
throw new Error(`Backup execution for schedule ${request.scheduleId} was not tracked`); throw new Error(`Backup execution for schedule ${request.scheduleId} was not tracked`);
} }
const jobId = Bun.randomUUIDv7();
if (request.signal.aborted) { if (request.signal.aborted) {
throw request.signal.reason || new Error("Operation aborted"); throw request.signal.reason || new Error("Operation aborted");
} }
const jobId = Bun.randomUUIDv7();
const payload = await createBackupRunPayload({ ...request, jobId }); const payload = await createBackupRunPayload({ ...request, jobId });
if (request.signal.aborted) { if (request.signal.aborted) {
throw request.signal.reason || new Error("Operation aborted"); throw request.signal.reason || new Error("Operation aborted");
} }
return agentManager.runBackup(LOCAL_AGENT_ID, { const executionResult = await agentManager.runBackup(LOCAL_AGENT_ID, {
scheduleId: request.scheduleId, scheduleId: request.scheduleId,
payload, payload,
signal: request.signal, signal: request.signal,
onProgress: request.onProgress, onProgress: request.onProgress,
}); });
if (executionResult.status === "unavailable" && !config.flags.enableLocalAgent) {
return executeBackupWithoutAgent(payload, request);
}
return executionResult;
}, },
cancel: async (scheduleId: number) => { cancel: async (scheduleId: number) => {
const abortController = activeControllersByScheduleId.get(scheduleId); const abortController = activeControllersByScheduleId.get(scheduleId);