diff --git a/Makefile b/Makefile index 62b6659..d919f4e 100644 --- a/Makefile +++ b/Makefile @@ -75,3 +75,8 @@ tree: @powershell -Command "git ls-files --exclude-standard | Select-String -NotMatch '$(EXCLUDE_CONTEXT_PREFIX)' | Out-File -Encoding UTF8 $(OUTPUT_FILE)" @powershell -Command "Add-Content -Path $(OUTPUT_FILE) -Value '$(EXCLUDE_CONTEXT_PREFIX)' -Encoding UTF8" @echo "The project file list has been generated to project_structure.txt" + +# 启用gemini-cli +.PHONY: gemini +gemini: + gemini -m "gemini-2.5-flash" \ No newline at end of file diff --git a/design/system-plan-continuously-triggered/index.md b/design/system-plan-continuously-triggered/index.md new file mode 100644 index 0000000..b0e2790 --- /dev/null +++ b/design/system-plan-continuously-triggered/index.md @@ -0,0 +1,21 @@ +# 问题 + +每次全量传感器采集都会连着下发五条采集指令 + +## issue + +http://git.huangwc.com/pig/pig-farm-controller/issues/55 + +# 解决方案 + +## 问题描述 + +系统启动时没有删掉旧的任务但会在更新时把新的任务插入, 导致计划中的任务越来越多 + +## 修复方案 + +系统启动更新系统计划时删掉旧的任务 + +## 其他修复 + +删除任务时对于设备任务关联表是软删除, 但这张表不支持软删除, 遂改为硬删除 \ No newline at end of file diff --git a/internal/core/data_initializer.go b/internal/core/data_initializer.go index a827c24..25d2f8d 100644 --- a/internal/core/data_initializer.go +++ b/internal/core/data_initializer.go @@ -70,11 +70,20 @@ func (app *Application) initializeSystemPlans(ctx context.Context) error { predefinedPlan.ID = foundExistingPlan.ID predefinedPlan.ExecuteCount = foundExistingPlan.ExecuteCount - if err := app.Infra.repos.planRepo.UpdatePlan(appCtx, predefinedPlan); err != nil { - return fmt.Errorf("更新预定义计划 '%s' 失败: %w", predefinedPlan.Name, err) - } else { - logger.Infof("成功更新预定义计划 '%s'。", predefinedPlan.Name) + // 1. 使用 UpdatePlanMetadataAndStructure 来更新计划的元数据和关联任务 + // 这会处理 Name, Description, ExecutionType, ExecuteNum, CronExpression, ContentType + // 并且最重要的是,它会正确处理 Tasks 的增删改,确保任务列表与 predefinedPlan.Tasks 完全同步 + if err := app.Infra.repos.planRepo.UpdatePlanMetadataAndStructure(appCtx, predefinedPlan); err != nil { + return fmt.Errorf("更新预定义计划 '%s' 的元数据和结构失败: %w", predefinedPlan.Name, err) } + + // 2. 接着使用 UpdatePlan 来更新所有顶层字段,包括 PlanType 和 Status + // 由于任务已经在上一步正确同步,此步不会导致任务冗余 + if err := app.Infra.repos.planRepo.UpdatePlan(appCtx, predefinedPlan); err != nil { + return fmt.Errorf("更新预定义计划 '%s' 的所有顶层字段失败: %w", predefinedPlan.Name, err) + } + + logger.Infof("成功更新预定义计划 '%s'。", predefinedPlan.Name) } else { // 如果计划不存在, 则创建 logger.Infof("预定义计划 '%s' 不存在,正在创建...", predefinedPlan.Name) diff --git a/internal/infra/repository/plan_repository.go b/internal/infra/repository/plan_repository.go index cfaf01d..6ce886b 100644 --- a/internal/infra/repository/plan_repository.go +++ b/internal/infra/repository/plan_repository.go @@ -608,7 +608,7 @@ func (r *gormPlanRepository) deleteTasksTx(ctx context.Context, tx *gorm.DB, ids // 1. 直接、高效地从关联表中物理删除所有相关记录 // 这是最关键的优化,避免了不必要的查询和循环 - if err := tx.WithContext(repoCtx).Where("task_id IN ?", ids).Delete(&models.DeviceTask{}).Error; err != nil { + if err := tx.WithContext(repoCtx).Where("task_id IN ?", ids).Unscoped().Delete(&models.DeviceTask{}).Error; err != nil { return fmt.Errorf("清理任务的设备关联失败: %w", err) }