feat(backup): add scheduler alerts and recovery notifications
This commit is contained in:
+10
-69
@@ -2,7 +2,6 @@
|
||||
import { resolve } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { mkdirSync } from 'fs';
|
||||
import { Cron } from 'croner';
|
||||
|
||||
// ── Config & Types ──
|
||||
import type { Config } from '../config/index.js';
|
||||
@@ -34,7 +33,7 @@ import type { McpManager } from '../mcp/index.js';
|
||||
import type { SkillRegistry, SkillInstaller } from '../skills/index.js';
|
||||
import type { GatewayServer } from '../gateway/index.js';
|
||||
import { AuditLogger, initAuditLogger } from '../audit/index.js';
|
||||
import { runBackupSnapshot } from '../backup/index.js';
|
||||
import { BackupScheduler } from '../backup/index.js';
|
||||
|
||||
export interface DaemonContext {
|
||||
config: Config;
|
||||
@@ -105,73 +104,6 @@ export async function startDaemon(config: Config, options?: StartDaemonOptions):
|
||||
lifecycle.onShutdown(async () => { clearInterval(pruneInterval); });
|
||||
}
|
||||
|
||||
if (config.backup.enabled) {
|
||||
const backupIntervalMs = parseDuration(config.backup.interval);
|
||||
const backupSchedule = config.backup.schedule?.trim();
|
||||
if (!backupSchedule && !backupIntervalMs) {
|
||||
console.warn(`Backup enabled but interval is invalid: ${config.backup.interval}`);
|
||||
} else {
|
||||
let backupRunning = false;
|
||||
const runScheduledBackup = async (): Promise<void> => {
|
||||
if (backupRunning) {
|
||||
return;
|
||||
}
|
||||
backupRunning = true;
|
||||
try {
|
||||
const result = await runBackupSnapshot({
|
||||
dataDir,
|
||||
backupConfig: config.backup,
|
||||
});
|
||||
console.log(`Backup completed: ${result.archivePath}${result.uploaded && result.remotePath ? ` -> ${result.remotePath}` : ''}`);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
console.error(`Backup failed: ${message}`);
|
||||
} finally {
|
||||
backupRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
let backupCron: Cron | undefined;
|
||||
let backupInterval: ReturnType<typeof setInterval> | undefined;
|
||||
|
||||
if (backupSchedule) {
|
||||
try {
|
||||
backupCron = new Cron(backupSchedule, { paused: false }, () => {
|
||||
void runScheduledBackup();
|
||||
});
|
||||
console.log(`Backup scheduler enabled (cron: ${backupSchedule})`);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
console.warn(`Backup cron schedule is invalid (${backupSchedule}): ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!backupCron && backupIntervalMs) {
|
||||
backupInterval = setInterval(() => {
|
||||
void runScheduledBackup();
|
||||
}, backupIntervalMs);
|
||||
console.log(`Backup scheduler enabled (interval: ${config.backup.interval})`);
|
||||
}
|
||||
|
||||
if (!backupCron && !backupInterval) {
|
||||
console.warn('Backup scheduler disabled: no valid backup.schedule or backup.interval');
|
||||
} else {
|
||||
if (config.backup.run_on_start) {
|
||||
void runScheduledBackup();
|
||||
}
|
||||
|
||||
lifecycle.onShutdown(async () => {
|
||||
if (backupCron) {
|
||||
backupCron.stop();
|
||||
}
|
||||
if (backupInterval) {
|
||||
clearInterval(backupInterval);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Core Services ──
|
||||
const hookEngine = new HookEngine(config.hooks);
|
||||
const { toolRegistry, toolExecutor, browserManager } = initTools({ config, lifecycle, hookEngine });
|
||||
@@ -256,6 +188,15 @@ export async function startDaemon(config: Config, options?: StartDaemonOptions):
|
||||
|
||||
// ── Lifecycle ──
|
||||
await startServices({ config, lifecycle, channelRegistry, gateway, modelRouter, memoryDir, dataDir });
|
||||
const backupScheduler = new BackupScheduler({
|
||||
dataDir,
|
||||
backupConfig: config.backup,
|
||||
channelLookup: channelRegistry,
|
||||
});
|
||||
backupScheduler.start();
|
||||
lifecycle.onShutdown(async () => {
|
||||
backupScheduler.stop();
|
||||
});
|
||||
|
||||
return {
|
||||
config, lifecycle, sessionStore, sessionManager, hookEngine, modelRouter,
|
||||
|
||||
Reference in New Issue
Block a user