TaskCancelledDomainEventHandler.cs 5.94 KB
using Microsoft.Extensions.Logging;
using Rcs.Application.Services.Protocol;
using Rcs.Domain.Entities;
using Rcs.Domain.Entities.DomainEvents.RobotTask;
using Rcs.Domain.Repositories;
using Rcs.Infrastructure.DB.MsSql;

namespace Rcs.Infrastructure.MessageBus.Handlers.Events.RobotTask
{
    /// <summary>
    /// 任务取消领域事件处理器
    /// @author zzy
    /// </summary>
    public class TaskCancelledDomainEventHandler
    {
        private readonly ILogger<TaskCancelledDomainEventHandler> _logger;
        private readonly IProtocolServiceFactory _protocolServiceFactory;
        private readonly IRobotTaskRepository _robotTaskRepository;
        private readonly IRobotRepository _robotRepository;
        private readonly AppDbContext _dbContext;
        public TaskCancelledDomainEventHandler(
            IProtocolServiceFactory protocolServiceFactory,
            IRobotTaskRepository robotTaskRepository,
            IRobotRepository robotRepository,
            AppDbContext dbContext,
            ILogger<TaskCancelledDomainEventHandler> logger)
        {
            _logger = logger;
            _protocolServiceFactory = protocolServiceFactory;
            _robotTaskRepository = robotTaskRepository;
            _robotRepository = robotRepository;
            _dbContext = dbContext;
        }

        public async System.Threading.Tasks.Task Handle(TaskCancelledDomainEvent domainEvent)
        {
            if (domainEvent.RobotId.HasValue)
            {
                var robot = await _robotRepository.GetByIdAsync(domainEvent.RobotId);
                if (robot == null) return;
                // 根据协议类型获取对应的协议服务
                var protocolService = _protocolServiceFactory.GetService(robot);

                // 取消机器人任务
                await protocolService.CancelRobotTasksAsync(robot);
            }

            var task = await _robotTaskRepository.GetByIdWithDetailsAsync(domainEvent.TaskId);
            if (task == null)
            {
                _logger.LogWarning("鍙栨秷浠诲姟涓嶅瓨鍦? {TaskId}", domainEvent.TaskId);
                return;
            }

            await ReleaseTaskShelfAndRobotCacheLocationAsync(task);
            await ArchiveCancelledTaskAsync(task);
        }

        private async Task ReleaseTaskShelfAndRobotCacheLocationAsync(Rcs.Domain.Entities.RobotTask task)
        {
            var shelfCode = task.ShelfCode;
            var containerId = task.ContainerID;

            if (task.RobotId.HasValue)
            {
                var robot = await _robotRepository.GetByIdFullDataAsync(task.RobotId.Value);
                if (robot != null)
                {
                    var targetCacheLocation = robot.CacheLocations
                        .FirstOrDefault(c => !string.IsNullOrWhiteSpace(shelfCode) && c.LocationCode == shelfCode)
                        ?? robot.CacheLocations.FirstOrDefault(c => !string.IsNullOrWhiteSpace(containerId) && c.ContainerId == containerId);

                    if (targetCacheLocation != null)
                    {
                        targetCacheLocation.ContainerId = null;
                        targetCacheLocation.UpdatedAt = DateTime.Now;
                        
                        await _robotRepository.UpdateAsync(robot);
                        await _robotRepository.SaveChangesAsync();
                    }
                }
            }

            task.ShelfCode = null;
            task.UpdatedAt = DateTime.Now;
            await _robotTaskRepository.UpdateAsync(task);
            await _robotTaskRepository.SaveChangesAsync();
        }

        private async System.Threading.Tasks.Task ArchiveCancelledTaskAsync(Rcs.Domain.Entities.RobotTask task)
        {
            var archivedAt = DateTime.Now;

            var taskHistory = new RobotTaskHistory
            {
                TaskId = task.TaskId,
                TaskCode = task.TaskCode,
                TaskName = task.TaskName,
                RobotCode = task.Robot?.RobotCode,
                TaskTemplateCode = task.TaskTemplate?.TemplateCode,
                BeginLocationCode = task.BeginLocation?.LocationCode,
                EndLocationCode = task.EndLocation?.LocationCode,
                Status = task.Status,
                Pause = task.Pause,
                Priority = task.Priority,
                Source = task.Source,
                Relation = task.Relation,
                ShelfCode = task.ShelfCode,
                ContainerID = task.ContainerID,
                ErrorInfo = task.ErrorInfo,
                CreatedAt = task.CreatedAt,
                UpdatedAt = task.UpdatedAt,
                ArchivedAt = archivedAt
            };

            var subTaskHistories = task.SubTasks.Select(subTask => new RobotSubTaskHistory
            {
                SubTaskId = subTask.SubTaskId,
                TaskCode = task.TaskCode,
                RobotCode = subTask.Robot?.RobotCode,
                BeginNodeCode = subTask.BeginNode?.NodeCode ?? string.Empty,
                EndNodeCode = subTask.EndNode?.NodeCode ?? string.Empty,
                Sequence = subTask.Sequence,
                Status = subTask.Status,
                ExecutionCount = subTask.ExecutionCount,
                CreatedAt = subTask.CreatedAt,
                UpdatedAt = subTask.UpdatedAt,
                ArchivedAt = archivedAt
            }).ToList();

            await _dbContext.RobotTaskHistories.AddAsync(taskHistory);
            if (subTaskHistories.Count > 0)
            {
                await _dbContext.RobotSubTaskHistories.AddRangeAsync(subTaskHistories);
            }

            await _robotTaskRepository.DeleteAsync(task);
            await _robotTaskRepository.SaveChangesAsync();

            _logger.LogInformation(
                "鍙栨秷浠诲姟宸茶縼绉昏嚦鍘嗗彶琛? TaskId={TaskId}, TaskCode={TaskCode}, SubTaskCount={SubTaskCount}",
                task.TaskId,
                task.TaskCode,
                subTaskHistories.Count);
        }
    }
}