fix(ops-cleanup): 让 UI 数据保留策略真正生效

UI 上 admin 改的数据保留策略(cron + retention 天数)此前只写入 settings 表的
ops_advanced_settings.data_retention,但 OpsCleanupService 启动时只读
cfg.Ops.Cleanup(config.yaml / 环境变量),从未读取 settings 表,导致 UI 配置
完全不生效——cron 实际仍按默认 0 2 * * * 每日跑、retention 30 天。

改动:
- OpsCleanupService 增加 settingRepo 依赖,新增 effective 配置 + Reload 方法。
  Start/Reload 时从 settings.ops_advanced_settings.data_retention 覆盖
  cfg.Ops.Cleanup(Enabled、Schedule、*RetentionDays),无 settings 时整体
  fallback 到 cfg。runScheduled 顶部刷新一次 effective,让 retention 改动当次
  即生效(schedule/enabled 改动需要 Reload 才换 cron)。
- 用 mu + started/stopped 替换 startOnce/stopOnce 以支持 Reload 重建 cron。
- OpsService 增加 CleanupReloader 接口与 SetCleanupReloader setter;
  UpdateOpsAdvancedSettings 写入后调用 Reload。
- wire 通过 setter 注入 cleanup hook,避免构造期循环依赖。
- 新增单测覆盖 overlay 五种情形 + Update 触发 Reload。
This commit is contained in:
erio
2026-05-04 11:36:41 +08:00
parent df722c9a6e
commit c4598aa9b6
6 changed files with 406 additions and 45 deletions

View File

@@ -54,6 +54,24 @@ type OpsService struct {
geminiCompatService *GeminiMessagesCompatService
antigravityGatewayService *AntigravityGatewayService
systemLogSink *OpsSystemLogSink
// cleanupReloader 由 wire 在 OpsCleanupService 构造完成后通过 SetCleanupReloader 注入。
// 解耦避免 OpsService -> OpsCleanupService 的硬依赖cleanup 也读 settings会循环
cleanupReloader CleanupReloader
}
// CleanupReloader 由 OpsCleanupService 实现。
// UpdateOpsAdvancedSettings 写入新配置后调用 Reload让 schedule/enabled 改动立刻生效。
type CleanupReloader interface {
Reload(ctx context.Context) error
}
// SetCleanupReloader 由 wire 注入 cleanup hook构造期循环依赖的解耦点
func (s *OpsService) SetCleanupReloader(r CleanupReloader) {
if s == nil {
return
}
s.cleanupReloader = r
}
func NewOpsService(