fix(FN-XXXX): run auto-backup in-process to stop nested .fusion creation
The backup automation was scheduled with `npx runfusion.ai backup --create`, which spawns whatever fusion binary is on PATH. On developer machines that's usually an older globally-installed runfusion.ai (v0.13.0 at time of writing) which still carries the pluginStore-rootDir bug — every backup tick recreated `<project>/.fusion/.fusion/` with a fresh empty TaskStore. Cron-runner and routine-runner now intercept any command matching `fn backup`, `fusion backup`, or `npx runfusion.ai backup` and call `runBackupCommand` directly via the engine's open TaskStore. The interception also handles existing schedules persisted with the old npx command, so users do not need to manually update their automation rows. The default command for newly created backup schedules is also simplified to `fn backup --create` — both forms route through the same in-process executor. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -474,7 +474,7 @@ describe("syncBackupRoutine", () => {
|
||||
expect(routine).toBeDefined();
|
||||
expect(routine?.name).toBe("Database Backup");
|
||||
expect(routine?.trigger).toEqual({ type: "cron", cronExpression: "0 3 * * *" });
|
||||
expect(routine?.command).toBe("npx runfusion.ai backup --create");
|
||||
expect(routine?.command).toBe("fn backup --create");
|
||||
expect(routine?.agentId).toBe("");
|
||||
expect(routine?.scope).toBe("project");
|
||||
});
|
||||
@@ -495,7 +495,7 @@ describe("syncBackupRoutine", () => {
|
||||
|
||||
expect(routines).toHaveLength(1);
|
||||
expect(updated?.trigger).toEqual({ type: "cron", cronExpression: "30 4 * * *" });
|
||||
expect(updated?.command).toBe("npx runfusion.ai backup --create");
|
||||
expect(updated?.command).toBe("fn backup --create");
|
||||
expect(updated?.enabled).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -411,7 +411,13 @@ export async function syncBackupAutomation(
|
||||
// Build the backup command.
|
||||
// Uses `npx runfusion.ai` so backups work even when only the zero-install
|
||||
// path (`npx runfusion.ai`) has been used and `fn` is not on PATH.
|
||||
const command = "npx runfusion.ai backup --create";
|
||||
// Sentinel command intercepted in-process by the engine's cron/routine
|
||||
// runner (see `isInProcessBackupCommand` in @fusion/engine). Stored as a
|
||||
// command rather than a step so existing UI listings still display it as
|
||||
// a single-line action. Falls back to the npx shell-out only when read by
|
||||
// a runner that does not implement the in-process interception (e.g.
|
||||
// outdated globally-installed binaries running an older fusion engine).
|
||||
const command = "fn backup --create";
|
||||
|
||||
if (existingSchedule) {
|
||||
// Update existing schedule
|
||||
@@ -462,7 +468,13 @@ export async function syncBackupRoutine(
|
||||
throw new Error(`Invalid backup schedule: ${schedule}`);
|
||||
}
|
||||
|
||||
const command = "npx runfusion.ai backup --create";
|
||||
// Sentinel command intercepted in-process by the engine's cron/routine
|
||||
// runner (see `isInProcessBackupCommand` in @fusion/engine). Stored as a
|
||||
// command rather than a step so existing UI listings still display it as
|
||||
// a single-line action. Falls back to the npx shell-out only when read by
|
||||
// a runner that does not implement the in-process interception (e.g.
|
||||
// outdated globally-installed binaries running an older fusion engine).
|
||||
const command = "fn backup --create";
|
||||
const input = {
|
||||
name: BACKUP_SCHEDULE_NAME,
|
||||
description: "Automatic database backup based on project settings",
|
||||
|
||||
Reference in New Issue
Block a user