fix: address review findings for backup management
- HIGH: Add sync.Mutex to backup Engine to prevent concurrent backup/restore operations - HIGH: Restore uses io.Copy instead of ReadFile to avoid OOM on large databases - HIGH: Send HTTP response before closing DB during restore, then perform destructive operations in a goroutine - HIGH: Create pre-restore safety backup before overwriting database - HIGH: Autobackup cron reschedules dynamically when settings change via callback pattern (same as DNS provider changes)
This commit is contained in:
+20
-7
@@ -224,10 +224,20 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule autobackup if enabled.
|
||||
if settings.BackupEnabled && settings.BackupIntervalHours > 0 {
|
||||
interval := fmt.Sprintf("@every %dh", settings.BackupIntervalHours)
|
||||
if _, err := cronScheduler.AddFunc(interval, func() {
|
||||
// Schedule autobackup if enabled. Track entry ID for rescheduling.
|
||||
var backupCronID cron.EntryID
|
||||
scheduleAutobackup := func(enabled bool, intervalHours int) {
|
||||
// Remove existing schedule if any.
|
||||
if backupCronID != 0 {
|
||||
cronScheduler.Remove(backupCronID)
|
||||
backupCronID = 0
|
||||
slog.Info("autobackup: removed previous schedule")
|
||||
}
|
||||
if !enabled || intervalHours <= 0 {
|
||||
return
|
||||
}
|
||||
interval := fmt.Sprintf("@every %dh", intervalHours)
|
||||
id, err := cronScheduler.AddFunc(interval, func() {
|
||||
b, err := backupEngine.CreateBackup("auto")
|
||||
if err != nil {
|
||||
slog.Error("autobackup failed", "error", err)
|
||||
@@ -235,17 +245,19 @@ func main() {
|
||||
}
|
||||
slog.Info("autobackup completed", "id", b.ID, "filename", b.Filename)
|
||||
|
||||
// Prune after auto backup.
|
||||
currentSettings, err := db.GetSettings()
|
||||
if err == nil && currentSettings.BackupRetentionCount > 0 {
|
||||
backupEngine.Prune(currentSettings.BackupRetentionCount)
|
||||
}
|
||||
}); err != nil {
|
||||
})
|
||||
if err != nil {
|
||||
slog.Warn("failed to schedule autobackup", "error", err)
|
||||
} else {
|
||||
slog.Info("autobackup scheduled", "interval_hours", settings.BackupIntervalHours)
|
||||
backupCronID = id
|
||||
slog.Info("autobackup scheduled", "interval_hours", intervalHours)
|
||||
}
|
||||
}
|
||||
scheduleAutobackup(settings.BackupEnabled, settings.BackupIntervalHours)
|
||||
|
||||
// Build API server.
|
||||
apiServer := api.NewServer(db, dockerClient, npmClient, dep, webhookHandler, eventBus, encKey)
|
||||
@@ -253,6 +265,7 @@ func main() {
|
||||
apiServer.SetProxyManager(proxyManager)
|
||||
apiServer.SetBackupEngine(backupEngine)
|
||||
apiServer.SetDBPath(dbPath)
|
||||
apiServer.SetBackupSettingsChangedCallback(scheduleAutobackup)
|
||||
apiServer.SetDNSProvider(dnsProvider)
|
||||
apiServer.SetDNSProviderChangedCallback(func(provider dns.Provider) {
|
||||
dep.SetDNSProvider(provider)
|
||||
|
||||
Reference in New Issue
Block a user