重构AnalysisPlanTaskManager
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -112,10 +112,9 @@ type Scheduler struct {
|
||||
progressTracker *ProgressTracker
|
||||
taskFactory func(taskType models.TaskType) Task // 调度器需要注入一个任务工厂,用于创建任务实例
|
||||
|
||||
pool *ants.Pool // 使用 ants 协程池来管理并发
|
||||
wg sync.WaitGroup
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
pool *ants.Pool // 使用 ants 协程池来管理并发
|
||||
wg sync.WaitGroup
|
||||
stopChan chan struct{} // 用于停止主循环的信号通道
|
||||
}
|
||||
|
||||
// NewScheduler 创建一个新的调度器实例
|
||||
@@ -128,8 +127,6 @@ func NewScheduler(
|
||||
logger *logs.Logger,
|
||||
interval time.Duration,
|
||||
numWorkers int) *Scheduler {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
return &Scheduler{
|
||||
pendingTaskRepo: pendingTaskRepo,
|
||||
executionLogRepo: executionLogRepo,
|
||||
@@ -140,8 +137,7 @@ func NewScheduler(
|
||||
workers: numWorkers,
|
||||
progressTracker: NewProgressTracker(),
|
||||
taskFactory: taskFactory,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
stopChan: make(chan struct{}), // 初始化停止信号通道
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +160,9 @@ func (s *Scheduler) Start() {
|
||||
// Stop 优雅地停止调度器
|
||||
func (s *Scheduler) Stop() {
|
||||
s.logger.Warnf("正在停止任务调度器...")
|
||||
s.cancel() // 1. 发出取消信号,停止主循环
|
||||
s.wg.Wait() // 2. 等待主循环完成
|
||||
s.pool.Release() // 3. 释放 ants 池 (等待所有已提交的任务执行完毕)
|
||||
close(s.stopChan) // 1. 发出停止信号,停止主循环
|
||||
s.wg.Wait() // 2. 等待主循环完成
|
||||
s.pool.Release() // 3. 释放 ants 池 (等待所有已提交的任务执行完毕)
|
||||
s.logger.Warnf("任务调度器已安全停止")
|
||||
}
|
||||
|
||||
@@ -178,9 +174,11 @@ func (s *Scheduler) run() {
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
case <-s.stopChan:
|
||||
// 收到停止信号,退出循环
|
||||
return
|
||||
case <-ticker.C:
|
||||
// 定时触发任务认领和提交
|
||||
go s.claimAndSubmit()
|
||||
}
|
||||
}
|
||||
@@ -256,10 +254,26 @@ func (s *Scheduler) processTask(claimedLog *models.TaskExecutionLog) {
|
||||
|
||||
// 任务计数器校验, Plan的任务全部执行完成后需要插入一个新的PlanAnalysisTask用于触发下一次Plan的执行
|
||||
if s.progressTracker.IsPlanOver(claimedLog.PlanExecutionLogID) {
|
||||
// 调用共享的 Manager 来处理触发器更新逻辑
|
||||
err = s.analysisPlanTaskManager.CreateOrUpdateTrigger(s.ctx, claimedLog.Task.PlanID)
|
||||
// --- 新增逻辑:更新计划执行次数并判断是否需要触发下一次执行 ---
|
||||
planID := claimedLog.Task.PlanID
|
||||
|
||||
// 获取计划的最新数据
|
||||
plan, err := s.planRepo.GetBasicPlanByID(planID)
|
||||
if err != nil {
|
||||
s.logger.Errorf("[严重] 创建计划分析任务失败, 当前Plan(%v)将无法进行下次触发, 错误: %v", claimedLog.Task.PlanID, err)
|
||||
s.logger.Errorf("获取计划 %d 的基本信息失败: %v", planID, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 更新计划的执行计数器
|
||||
plan.ExecuteCount++
|
||||
if err := s.planRepo.UpdatePlan(plan); err != nil { // UpdatePlan 可以更新整个 Plan 对象
|
||||
s.logger.Errorf("更新计划 %d 的执行计数失败: %v", planID, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 调用共享的 Manager 来处理触发器更新逻辑
|
||||
if err := s.analysisPlanTaskManager.CreateOrUpdateTrigger(planID); err != nil {
|
||||
s.logger.Errorf("为计划 %d 创建/更新触发器失败: %v", planID, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,8 +315,18 @@ func (s *Scheduler) runTask(claimedLog *models.TaskExecutionLog) error {
|
||||
// analysisPlan 解析Plan并将解析出的Task列表插入待执行队列中
|
||||
func (s *Scheduler) analysisPlan(claimedLog *models.TaskExecutionLog) error {
|
||||
// 创建Plan执行记录
|
||||
// 从任务的 Parameters 中解析出真实的 PlanID
|
||||
var params struct {
|
||||
PlanID uint `json:"plan_id"`
|
||||
}
|
||||
if err := json.Unmarshal(claimedLog.Task.Parameters, ¶ms); err != nil {
|
||||
s.logger.Errorf("解析任务参数中的计划ID失败,日志ID: %d, 错误: %v", claimedLog.ID, err)
|
||||
return err
|
||||
}
|
||||
realPlanID := params.PlanID
|
||||
|
||||
planLog := &models.PlanExecutionLog{
|
||||
PlanID: claimedLog.Task.PlanID,
|
||||
PlanID: realPlanID, // 使用从参数中解析出的真实 PlanID
|
||||
Status: models.ExecutionStatusStarted,
|
||||
StartedAt: time.Now(),
|
||||
}
|
||||
@@ -312,7 +336,7 @@ func (s *Scheduler) analysisPlan(claimedLog *models.TaskExecutionLog) error {
|
||||
}
|
||||
|
||||
// 解析出Task列表
|
||||
tasks, err := s.planRepo.FlattenPlanTasks(claimedLog.Task.PlanID)
|
||||
tasks, err := s.planRepo.FlattenPlanTasks(realPlanID)
|
||||
if err != nil {
|
||||
s.logger.Errorf("[严重] 解析计划失败, 日志ID: %d, 错误: %v", claimedLog.ID, err)
|
||||
return err
|
||||
@@ -320,12 +344,12 @@ func (s *Scheduler) analysisPlan(claimedLog *models.TaskExecutionLog) error {
|
||||
|
||||
// 写入执行历史
|
||||
taskLogs := make([]*models.TaskExecutionLog, len(tasks))
|
||||
for _, task := range tasks {
|
||||
taskLogs = append(taskLogs, &models.TaskExecutionLog{
|
||||
for i, task := range tasks {
|
||||
taskLogs[i] = &models.TaskExecutionLog{
|
||||
PlanExecutionLogID: planLog.ID,
|
||||
TaskID: task.ID,
|
||||
Status: models.ExecutionStatusWaiting,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
err = s.executionLogRepo.CreateTaskExecutionLogsInBatch(taskLogs)
|
||||
@@ -337,13 +361,13 @@ func (s *Scheduler) analysisPlan(claimedLog *models.TaskExecutionLog) error {
|
||||
// 写入待执行队列
|
||||
pendingTasks := make([]*models.PendingTask, len(tasks))
|
||||
for i, task := range tasks {
|
||||
pendingTasks = append(pendingTasks, &models.PendingTask{
|
||||
pendingTasks[i] = &models.PendingTask{
|
||||
TaskID: task.ID,
|
||||
TaskExecutionLogID: pendingTasks[i].ID,
|
||||
TaskExecutionLogID: taskLogs[i].ID, // 使用正确的 TaskExecutionLogID
|
||||
|
||||
// 待执行队列是通过任务触发时间排序的, 且只要在调度器获取的时间点之前的都可以被触发
|
||||
ExecuteAt: time.Now().Add(time.Duration(i) * time.Second),
|
||||
})
|
||||
}
|
||||
}
|
||||
err = s.pendingTaskRepo.CreatePendingTasksInBatch(pendingTasks)
|
||||
if err != nil {
|
||||
@@ -352,7 +376,7 @@ func (s *Scheduler) analysisPlan(claimedLog *models.TaskExecutionLog) error {
|
||||
}
|
||||
|
||||
// 将Task列表加入待执行队列中
|
||||
s.progressTracker.AddNewPlan(claimedLog.PlanExecutionLogID, len(tasks))
|
||||
s.progressTracker.AddNewPlan(planLog.ID, len(tasks))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user