diff --git a/internal/core/application.go b/internal/core/application.go index 753a44a..e8815a7 100644 --- a/internal/core/application.go +++ b/internal/core/application.go @@ -192,6 +192,30 @@ func (app *Application) initializePendingTasks( // 阶段二:清理所有待执行任务和相关日志 logger.Info("阶段二:开始清理所有待执行任务和相关日志...") + // --- 新增逻辑:处理因崩溃导致状态不一致的计划主表状态 --- + // 1. 查找所有未完成的计划执行日志 (状态为 Started 或 Waiting) + incompletePlanLogs, err := executionLogRepo.FindIncompletePlanExecutionLogs() + if err != nil { + return fmt.Errorf("查找未完成的计划执行日志失败: %w", err) + } + + // 2. 收集所有受影响的唯一 PlanID + affectedPlanIDs := make(map[uint]struct{}) + for _, log := range incompletePlanLogs { + affectedPlanIDs[log.PlanID] = struct{}{} + } + + // 3. 对于每个受影响的 PlanID,重置其 execute_count 并将其状态设置为 Failed + for planID := range affectedPlanIDs { + logger.Warnf("检测到计划 #%d 在应用崩溃前处于未完成状态,将重置其计数并标记为失败。", planID) + // 使用 UpdatePlanStateAfterExecution 来更新主表状态,避免影响关联数据 + if err := planRepo.UpdatePlanStateAfterExecution(planID, 0, models.PlanStatusFailed); err != nil { + logger.Errorf("重置计划 #%d 计数并标记为失败时出错: %v", planID, err) + // 这是一个非阻塞性错误,继续处理其他计划 + } + } + logger.Info("阶段二:计划主表状态修正完成。") + // 直接调用新的方法来更新计划执行日志状态为失败 if err := executionLogRepo.FailAllIncompletePlanExecutionLogs(); err != nil { logger.Errorf("更新所有未完成计划执行日志状态为失败失败: %v", err)