增加任务增删改查时对设备任务关联表的维护
This commit is contained in:
		
							
								
								
									
										1
									
								
								internal/domain/plan/device_id_extractor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								internal/domain/plan/device_id_extractor.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
package plan
 | 
			
		||||
@@ -2,6 +2,7 @@ package plan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
 | 
			
		||||
@@ -55,25 +56,31 @@ type Service interface {
 | 
			
		||||
type planServiceImpl struct {
 | 
			
		||||
	executionManager ExecutionManager
 | 
			
		||||
	taskManager      AnalysisPlanTaskManager
 | 
			
		||||
	planRepo         repository.PlanRepository // 新增
 | 
			
		||||
	// deviceRepo       repository.DeviceRepository // 如果需要,新增
 | 
			
		||||
	logger *logs.Logger
 | 
			
		||||
	planRepo         repository.PlanRepository
 | 
			
		||||
	deviceRepo       repository.DeviceRepository
 | 
			
		||||
	unitOfWork       repository.UnitOfWork
 | 
			
		||||
	taskFactory      TaskFactory
 | 
			
		||||
	logger           *logs.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPlanService 创建一个新的 Service 实例。
 | 
			
		||||
func NewPlanService(
 | 
			
		||||
	executionManager ExecutionManager,
 | 
			
		||||
	taskManager AnalysisPlanTaskManager,
 | 
			
		||||
	planRepo repository.PlanRepository, // 新增
 | 
			
		||||
	// deviceRepo repository.DeviceRepository, // 如果需要,新增
 | 
			
		||||
	planRepo repository.PlanRepository,
 | 
			
		||||
	deviceRepo repository.DeviceRepository,
 | 
			
		||||
	unitOfWork repository.UnitOfWork,
 | 
			
		||||
	taskFactory TaskFactory,
 | 
			
		||||
	logger *logs.Logger,
 | 
			
		||||
) Service {
 | 
			
		||||
	return &planServiceImpl{
 | 
			
		||||
		executionManager: executionManager,
 | 
			
		||||
		taskManager:      taskManager,
 | 
			
		||||
		planRepo:         planRepo, // 注入
 | 
			
		||||
		// deviceRepo:       deviceRepo, // 注入
 | 
			
		||||
		logger: logger,
 | 
			
		||||
		planRepo:         planRepo,
 | 
			
		||||
		deviceRepo:       deviceRepo,
 | 
			
		||||
		unitOfWork:       unitOfWork,
 | 
			
		||||
		taskFactory:      taskFactory,
 | 
			
		||||
		logger:           logger,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -117,13 +124,40 @@ func (s *planServiceImpl) CreatePlan(planToCreate *models.Plan) (*models.Plan, e
 | 
			
		||||
	}
 | 
			
		||||
	planToCreate.ReorderSteps()
 | 
			
		||||
 | 
			
		||||
	// 3. 调用仓库方法创建计划
 | 
			
		||||
	if err := s.planRepo.CreatePlan(planToCreate); err != nil {
 | 
			
		||||
	// 3. 在调用仓库前,准备好所有数据,包括设备关联
 | 
			
		||||
	for i := range planToCreate.Tasks {
 | 
			
		||||
		taskModel := &planToCreate.Tasks[i]
 | 
			
		||||
		// 使用工厂创建临时领域对象
 | 
			
		||||
		taskResolver, err := s.taskFactory.CreateTaskFromModel(taskModel)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// 如果一个任务类型不支持,我们可以选择跳过或报错
 | 
			
		||||
			s.logger.Warnf("跳过为任务类型 '%s' 解析设备ID: %v", taskModel.Type, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		deviceIDs, err := taskResolver.ResolveDeviceIDs()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// 在事务外解析失败,直接返回错误
 | 
			
		||||
			return nil, fmt.Errorf("为任务 '%s' 提取设备ID失败: %w", taskModel.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(deviceIDs) > 0 {
 | 
			
		||||
			// 优化:无需查询完整的设备对象,只需构建包含ID的结构体即可建立关联
 | 
			
		||||
			devices := make([]models.Device, len(deviceIDs))
 | 
			
		||||
			for i, id := range deviceIDs {
 | 
			
		||||
				devices[i] = models.Device{Model: gorm.Model{ID: id}}
 | 
			
		||||
			}
 | 
			
		||||
			taskModel.Devices = devices
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 4. 调用仓库方法创建计划,该方法内部会处理事务
 | 
			
		||||
	err := s.planRepo.CreatePlan(planToCreate)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		s.logger.Errorf("%s: 数据库创建计划失败: %v", actionType, err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 4. 创建成功后,调用 manager 确保触发器任务定义存在,但不立即加入待执行队列
 | 
			
		||||
	// 5. 创建成功后,调用 manager 确保触发器任务定义存在,但不立即加入待执行队列
 | 
			
		||||
	if err := s.taskManager.EnsureAnalysisTaskDefinition(planToCreate.ID); err != nil {
 | 
			
		||||
		// 这是一个非阻塞性错误,我们只记录日志,因为主流程(创建计划)已经成功
 | 
			
		||||
		s.logger.Errorf("为新创建的计划 %d 确保触发器任务定义失败: %v", planToCreate.ID, err)
 | 
			
		||||
@@ -203,7 +237,32 @@ func (s *planServiceImpl) UpdatePlan(planToUpdate *models.Plan) (*models.Plan, e
 | 
			
		||||
	planToUpdate.ExecuteCount = 0
 | 
			
		||||
	s.logger.Infof("计划 #%d 被更新,执行计数器已重置为 0。", planToUpdate.ID)
 | 
			
		||||
 | 
			
		||||
	if err := s.planRepo.UpdatePlanMetadataAndStructure(planToUpdate); err != nil {
 | 
			
		||||
	// 在调用仓库前,准备好所有数据,包括设备关联
 | 
			
		||||
	for i := range planToUpdate.Tasks {
 | 
			
		||||
		taskModel := &planToUpdate.Tasks[i]
 | 
			
		||||
		taskResolver, err := s.taskFactory.CreateTaskFromModel(taskModel)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			s.logger.Warnf("跳过为任务类型 '%s' 解析设备ID: %v", taskModel.Type, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		deviceIDs, err := taskResolver.ResolveDeviceIDs()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("为任务 '%s' 提取设备ID失败: %w", taskModel.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(deviceIDs) > 0 {
 | 
			
		||||
			// 优化:无需查询完整的设备对象,只需构建包含ID的结构体即可建立关联
 | 
			
		||||
			devices := make([]models.Device, len(deviceIDs))
 | 
			
		||||
			for i, id := range deviceIDs {
 | 
			
		||||
				devices[i] = models.Device{Model: gorm.Model{ID: id}}
 | 
			
		||||
			}
 | 
			
		||||
			taskModel.Devices = devices
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 调用仓库方法更新计划,该方法内部会处理事务
 | 
			
		||||
	err = s.planRepo.UpdatePlanMetadataAndStructure(planToUpdate)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		s.logger.Errorf("%s: 数据库更新计划失败: %v, Plan: %+v", actionType, err, planToUpdate)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,4 +29,6 @@ type TaskDeviceIDResolver interface {
 | 
			
		||||
type TaskFactory interface {
 | 
			
		||||
	// Production 根据指定的任务执行日志创建一个任务实例。
 | 
			
		||||
	Production(claimedLog *models.TaskExecutionLog) Task
 | 
			
		||||
	// CreateTaskFromModel 仅根据任务模型创建一个任务实例,用于非执行场景(如参数解析)。
 | 
			
		||||
	CreateTaskFromModel(taskModel *models.Task) (TaskDeviceIDResolver, error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user