任务调度器关于任务执行部分实现(没测没检查, 但应该实现完了)

This commit is contained in:
2025-09-17 20:02:40 +08:00
parent e6047f6b6e
commit ceba0c280e
8 changed files with 392 additions and 36 deletions

View File

@@ -34,6 +34,12 @@ type PlanRepository interface {
UpdatePlan(plan *models.Plan) error
// DeletePlan 根据ID删除计划同时删除其关联的任务非子任务或子计划关联
DeletePlan(id uint) error
// FlattenPlanTasks 递归展开计划,返回按执行顺序排列的所有任务列表
FlattenPlanTasks(planID uint) ([]models.Task, error)
// DeleteTask 根据ID删除任务
DeleteTask(id int) error
// FindPlanAnalysisTaskByParamsPlanID 根据Parameters中的ParamsPlanID字段值查找TaskPlanAnalysis类型的Task
FindPlanAnalysisTaskByParamsPlanID(paramsPlanID uint) (*models.Task, error)
}
// gormPlanRepository 是 PlanRepository 的 GORM 实现
@@ -288,7 +294,7 @@ func (r *gormPlanRepository) reconcileTasks(tx *gorm.DB, plan *models.Plan) erro
return err
}
existingTaskMap := make(map[uint]bool)
existingTaskMap := make(map[int]bool)
for _, task := range existingTasks {
existingTaskMap[task.ID] = true
}
@@ -308,7 +314,7 @@ func (r *gormPlanRepository) reconcileTasks(tx *gorm.DB, plan *models.Plan) erro
}
}
var tasksToDelete []uint
var tasksToDelete []int
for id := range existingTaskMap {
tasksToDelete = append(tasksToDelete, id)
}
@@ -401,3 +407,116 @@ func (r *gormPlanRepository) DeletePlan(id uint) error {
return nil
})
}
// FlattenPlanTasks 递归展开计划,返回按执行顺序排列的所有任务列表
func (r *gormPlanRepository) FlattenPlanTasks(planID uint) ([]models.Task, error) {
plan, err := r.GetPlanByID(planID)
if err != nil {
return nil, fmt.Errorf("获取计划(ID: %d)失败: %w", planID, err)
}
return r.flattenPlanTasksRecursive(plan)
}
// flattenPlanTasksRecursive 递归展开计划的内部实现
func (r *gormPlanRepository) flattenPlanTasksRecursive(plan *models.Plan) ([]models.Task, error) {
var tasks []models.Task
switch plan.ContentType {
case models.PlanContentTypeTasks:
// 如果计划直接包含任务,直接返回这些任务
// 由于GetPlanByID已经预加载并排序了任务这里直接使用即可
tasks = append(tasks, plan.Tasks...)
case models.PlanContentTypeSubPlans:
// 如果计划包含子计划,则递归处理每个子计划
for _, subPlan := range plan.SubPlans {
// 获取子计划的任务列表
var subTasks []models.Task
var err error
// 确保子计划已经被加载
if subPlan.ChildPlan != nil {
subTasks, err = r.flattenPlanTasksRecursive(subPlan.ChildPlan)
} else {
// 如果子计划未加载,则从数据库获取并递归展开
subTasks, err = r.FlattenPlanTasks(subPlan.ChildPlanID)
}
if err != nil {
return nil, fmt.Errorf("展开子计划(ID: %d)失败: %w", subPlan.ChildPlanID, err)
}
// 将子计划的任务添加到结果中
tasks = append(tasks, subTasks...)
}
default:
return nil, fmt.Errorf("未知的计划内容类型: %v", plan.ContentType)
}
return tasks, nil
}
// DeleteTask 根据ID删除任务
func (r *gormPlanRepository) DeleteTask(id int) error {
// 使用事务确保操作的原子性
return r.db.Transaction(func(tx *gorm.DB) error {
// 1. 检查是否有待执行任务引用了这个任务
var pendingTaskCount int64
if err := tx.Model(&models.PendingTask{}).Where("task_id = ?", id).Count(&pendingTaskCount).Error; err != nil {
return fmt.Errorf("检查待执行任务时出错: %w", err)
}
// 如果有待执行任务引用该任务,不能删除
if pendingTaskCount > 0 {
return fmt.Errorf("无法删除任务(ID: %d),因为存在 %d 条待执行任务引用该任务", id, pendingTaskCount)
}
// 2. 检查是否有计划仍在使用这个任务
var planCount int64
if err := tx.Model(&models.Plan{}).Joins("JOIN tasks ON plans.id = tasks.plan_id").Where("tasks.id = ?", id).Count(&planCount).Error; err != nil {
return fmt.Errorf("检查计划引用任务时出错: %w", err)
}
// 如果有计划在使用该任务,不能删除
if planCount > 0 {
return fmt.Errorf("无法删除任务(ID: %d),因为存在 %d 个计划仍在使用该任务", id, planCount)
}
// 3. 执行删除操作
result := tx.Delete(&models.Task{}, id)
if result.Error != nil {
return fmt.Errorf("删除任务失败: %w", result.Error)
}
// 检查是否实际删除了记录
if result.RowsAffected == 0 {
return gorm.ErrRecordNotFound
}
return nil
})
}
// FindPlanAnalysisTaskByParamsPlanID 根据Parameters中的ParamsPlanID字段值查找TaskPlanAnalysis类型的Task
func (r *gormPlanRepository) FindPlanAnalysisTaskByParamsPlanID(paramsPlanID uint) (*models.Task, error) {
var task models.Task
// 构造JSON查询条件查找Parameters中包含指定ParamsPlanID且Type为TaskPlanAnalysis的任务
// TODO 在JSON字段中查找特定键值的语法取决于数据库类型这里使用PostgreSQL的语法
// TODO 如果使用的是MySQL则需要相应调整查询条件
result := r.db.Where(
"type = ? AND parameters->>'plan_id' = ?",
models.TaskPlanAnalysis,
fmt.Sprintf("%d", paramsPlanID),
).First(&task)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("未找到Parameters.PlanID为%d的TaskPlanAnalysis类型任务", paramsPlanID)
}
return nil, fmt.Errorf("查找任务时出错: %w", result.Error)
}
return &task, nil
}