diff --git a/Service/Jobs/DbBackupJob.cs b/Service/Jobs/DbBackupJob.cs new file mode 100644 index 0000000..4208fc4 --- /dev/null +++ b/Service/Jobs/DbBackupJob.cs @@ -0,0 +1,70 @@ +using Microsoft.Extensions.Hosting; +using Quartz; + +namespace Service.Jobs; + +/// +/// 数据库备份任务 +/// +public class DbBackupJob( + IHostEnvironment env, + ILogger logger) : IJob +{ + public Task Execute(IJobExecutionContext context) + { + try + { + logger.LogInformation("开始执行数据库备份任务"); + + // 数据库文件路径 (基于 appsettings.json 中的配置: database/EmailBill.db) + var dbPath = Path.Combine(env.ContentRootPath, "database", "EmailBill.db"); + var backupDir = Path.Combine(env.ContentRootPath, "database", "backups"); + + if (!File.Exists(dbPath)) + { + logger.LogWarning("数据库文件不存在,跳过备份: {Path}", dbPath); + return Task.CompletedTask; + } + + if (!Directory.Exists(backupDir)) + { + Directory.CreateDirectory(backupDir); + } + + // 创建备份 + var backupFileName = $"EmailBill_backup_{DateTime.Now:yyyyMMdd}.db"; + var backupPath = Path.Combine(backupDir, backupFileName); + + File.Copy(dbPath, backupPath, true); + logger.LogInformation("数据库备份成功: {Path}", backupPath); + + // 清理旧备份 (保留最近20个) + var files = new DirectoryInfo(backupDir).GetFiles("EmailBill_backup_*.db") + .OrderByDescending(f => f.LastWriteTime) // 使用 LastWriteTime 排序 + .ToList(); + + if (files.Count > 20) + { + var filesToDelete = files.Skip(20); + foreach (var file in filesToDelete) + { + try + { + file.Delete(); + logger.LogInformation("删除过期备份: {Name}", file.Name); + } + catch (Exception ex) + { + logger.LogError(ex, "删除过期备份失败: {Name}", file.Name); + } + } + } + } + catch (Exception ex) + { + logger.LogError(ex, "数据库备份任务执行失败"); + } + + return Task.CompletedTask; + } +} diff --git a/WebApi/Expand.cs b/WebApi/Expand.cs index e74d1ea..52a9270 100644 --- a/WebApi/Expand.cs +++ b/WebApi/Expand.cs @@ -44,6 +44,17 @@ public static class Expand .WithIdentity("BudgetArchiveTrigger") .WithCronSchedule("0 0 23 1 * ?") // 每个月1号晚11点执行 .WithDescription("每个月1号晚11点执行预算归档")); + + // 配置数据库备份任务 - 每天早上6点执行 + var dbBackupJobKey = new JobKey("DbBackupJob"); + q.AddJob(opts => opts + .WithIdentity(dbBackupJobKey) + .WithDescription("数据库备份任务")); + q.AddTrigger(opts => opts + .ForJob(dbBackupJobKey) + .WithIdentity("DbBackupTrigger") + .WithCronSchedule("0 0 6 * * ?") // 每天早上6点执行 + .WithDescription("每天早上6点执行数据库备份")); }); // 添加 Quartz Hosted Service