issue_10 #12
| @@ -246,48 +246,7 @@ func (s *Scheduler) processTask(claimedLog *models.TaskExecutionLog) { | ||||
| 	// 如果此计划执行中,未完成的任务只剩下当前这一个(因为当前任务的状态此时在数据库中仍为 'started'), | ||||
| 	// 则认为整个计划已完成。 | ||||
| 	if incompleteCount == 1 { | ||||
| 		s.logger.Infof("计划执行 %d 的所有任务已完成,开始处理计划完成逻辑...", claimedLog.PlanExecutionLogID) | ||||
|  | ||||
| 		// 通过 PlanExecutionLog 反查正确的顶层 PlanID | ||||
| 		planExecutionLog, err := s.executionLogRepo.FindPlanExecutionLogByID(claimedLog.PlanExecutionLogID) | ||||
| 		if err != nil { | ||||
| 			s.logger.Errorf("获取计划执行日志 %d 失败: %v", claimedLog.PlanExecutionLogID, err) | ||||
| 			return | ||||
| 		} | ||||
| 		planID := planExecutionLog.PlanID // 这才是正确的顶层计划ID | ||||
|  | ||||
| 		// 获取计划的最新数据,这里我们只需要基本信息来判断执行类型和次数 | ||||
| 		plan, err := s.planRepo.GetBasicPlanByID(planID) | ||||
| 		if err != nil { | ||||
| 			s.logger.Errorf("获取计划 %d 的基本信息失败: %v", planID, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// 在内存中计算新的计数值和状态 | ||||
| 		newExecuteCount := plan.ExecuteCount + 1 | ||||
| 		newStatus := plan.Status // 默认为当前状态 | ||||
|  | ||||
| 		// 如果是自动计划且达到执行次数上限,或计划是手动类型,则更新计划状态为已停止 | ||||
| 		if (plan.ExecutionType == models.PlanExecutionTypeAutomatic && plan.ExecuteNum > 0 && newExecuteCount >= plan.ExecuteNum) || plan.ExecutionType == models.PlanExecutionTypeManual { | ||||
| 			newStatus = models.PlanStatusStopeed | ||||
| 			s.logger.Infof("计划 %d 已完成执行,状态更新为 '执行完毕'。", planID) | ||||
| 		} | ||||
|  | ||||
| 		// 使用新的、专门的方法来原子性地更新计数值和状态 | ||||
| 		if err := s.planRepo.UpdatePlanStateAfterExecution(planID, newExecuteCount, newStatus); err != nil { | ||||
| 			s.logger.Errorf("更新计划 %d 的执行后状态失败: %v", planID, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// 更新计划执行日志状态为完成 | ||||
| 		if err := s.executionLogRepo.UpdatePlanExecutionLogStatus(claimedLog.PlanExecutionLogID, models.ExecutionStatusCompleted); err != nil { | ||||
| 			s.logger.Errorf("更新计划执行日志 %d 状态为 '完成' 失败: %v", claimedLog.PlanExecutionLogID, err) | ||||
| 		} | ||||
|  | ||||
| 		// 调用共享的 Manager 来处理触发器更新逻辑 | ||||
| 		if err := s.analysisPlanTaskManager.CreateOrUpdateTrigger(planID); err != nil { | ||||
| 			s.logger.Errorf("为计划 %d 创建/更新触发器失败: %v", planID, err) | ||||
| 		} | ||||
| 		s.handlePlanCompletion(claimedLog.PlanExecutionLogID) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -387,6 +346,13 @@ func (s *Scheduler) analysisPlan(claimedLog *models.TaskExecutionLog) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// --- 处理空计划的边缘情况 --- | ||||
| 	// 如果一个计划被解析后,发现其任务列表为空, | ||||
| 	// 那么它实际上已经“执行”完毕了,我们需要在这里手动为它创建下一次的触发器。 | ||||
| 	if len(tasks) == 0 { | ||||
| 		s.handlePlanCompletion(planLog.ID) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -429,3 +395,49 @@ func (s *Scheduler) handlePlanTermination(planLogID uint, reason string) { | ||||
| 		s.logger.Errorf("更新计划 %d 状态为 '失败' 时出错: %v", planLog.PlanID, err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // handlePlanCompletion 集中处理计划成功完成后的所有逻辑 | ||||
| func (s *Scheduler) handlePlanCompletion(planLogID uint) { | ||||
| 	s.logger.Infof("计划执行 %d 的所有任务已完成,开始处理计划完成逻辑...", planLogID) | ||||
|  | ||||
| 	// 1. 通过 PlanExecutionLog 反查正确的顶层 PlanID | ||||
| 	planExecutionLog, err := s.executionLogRepo.FindPlanExecutionLogByID(planLogID) | ||||
| 	if err != nil { | ||||
| 		s.logger.Errorf("获取计划执行日志 %d 失败: %v", planLogID, err) | ||||
| 		return | ||||
| 	} | ||||
| 	topLevelPlanID := planExecutionLog.PlanID // 这才是正确的顶层计划ID | ||||
|  | ||||
| 	// 2. 获取计划的最新数据,这里我们只需要基本信息来判断执行类型和次数 | ||||
| 	plan, err := s.planRepo.GetBasicPlanByID(topLevelPlanID) | ||||
| 	if err != nil { | ||||
| 		s.logger.Errorf("获取计划 %d 的基本信息失败: %v", topLevelPlanID, err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// 3. 在内存中计算新的计数值和状态 | ||||
| 	newExecuteCount := plan.ExecuteCount + 1 | ||||
| 	newStatus := plan.Status // 默认为当前状态 | ||||
|  | ||||
| 	// 如果是自动计划且达到执行次数上限,或计划是手动类型,则更新计划状态为已停止 | ||||
| 	if (plan.ExecutionType == models.PlanExecutionTypeAutomatic && plan.ExecuteNum > 0 && newExecuteCount >= plan.ExecuteNum) || plan.ExecutionType == models.PlanExecutionTypeManual { | ||||
| 		newStatus = models.PlanStatusStopeed | ||||
| 		s.logger.Infof("计划 %d 已完成执行,状态更新为 '执行完毕'。", topLevelPlanID) | ||||
| 	} | ||||
|  | ||||
| 	// 4. 使用专门的方法来原子性地更新计数值和状态 | ||||
| 	if err := s.planRepo.UpdatePlanStateAfterExecution(topLevelPlanID, newExecuteCount, newStatus); err != nil { | ||||
| 		s.logger.Errorf("更新计划 %d 的执行后状态失败: %v", topLevelPlanID, err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// 5. 更新计划执行日志状态为完成 | ||||
| 	if err := s.executionLogRepo.UpdatePlanExecutionLogStatus(planLogID, models.ExecutionStatusCompleted); err != nil { | ||||
| 		s.logger.Errorf("更新计划执行日志 %d 状态为 '完成' 失败: %v", planLogID, err) | ||||
| 	} | ||||
|  | ||||
| 	// 6. 调用共享的 Manager 来处理触发器更新逻辑 | ||||
| 	if err := s.analysisPlanTaskManager.CreateOrUpdateTrigger(topLevelPlanID); err != nil { | ||||
| 		s.logger.Errorf("为计划 %d 创建/更新触发器失败: %v", topLevelPlanID, err) | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user