任务调度器关于任务执行部分实现(没测没检查, 但应该实现完了)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user