ExecuteRobotSubTaskCommandHandler.cs
5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using MassTransit;
using Microsoft.Extensions.Logging;
using Rcs.Application.Common;
using Rcs.Application.Services;
using Rcs.Application.Services.Protocol;
using Rcs.Application.MessageBus.Commands;
using Rcs.Domain.Repositories;
using Rcs.Infrastructure.PathFinding.Services;
using TaskStatus = Rcs.Domain.Entities.TaskStatus;
namespace Rcs.Infrastructure.MessageBus.Handlers.Commands;
/// <summary>
/// 执行子任务命令处理器
/// 处理逻辑与 SubTaskCompletedDomainEventHandler 中前置清理保持一致:
/// 清理 VDA 路径缓存、清空机器人缓存 Path、释放交通控制锁
/// </summary>
public class ExecuteRobotSubTaskCommandHandler : IConsumer<ExecuteRobotSubTaskCommand>
{
private readonly ILogger<ExecuteRobotSubTaskCommandHandler> _logger;
private readonly IRobotSubTaskRepository _robotSubTaskRepository;
private readonly IRobotTaskRepository _robotTaskRepository;
private readonly IRobotRepository _robotRepository;
private readonly IRobotCacheService _robotCacheService;
private readonly AgvPathService _agvPathService;
private readonly IProtocolServiceFactory _protocolServiceFactory;
public ExecuteRobotSubTaskCommandHandler(
ILogger<ExecuteRobotSubTaskCommandHandler> logger,
IRobotSubTaskRepository robotSubTaskRepository,
IRobotTaskRepository robotTaskRepository,
IRobotRepository robotRepository,
IRobotCacheService robotCacheService,
AgvPathService agvPathService,
IProtocolServiceFactory protocolServiceFactory)
{
_logger = logger;
_robotSubTaskRepository = robotSubTaskRepository;
_robotTaskRepository = robotTaskRepository;
_robotRepository = robotRepository;
_robotCacheService = robotCacheService;
_agvPathService = agvPathService;
_protocolServiceFactory = protocolServiceFactory;
}
public async Task Consume(ConsumeContext<ExecuteRobotSubTaskCommand> context)
{
var command = context.Message;
try
{
var subTask = await _robotSubTaskRepository.GetByIdWithDetailsAsync(command.SubTaskId, context.CancellationToken);
if (subTask == null)
{
await context.RespondAsync(ApiResponse.Failed($"未找到子任务ID为 {command.SubTaskId} 的任务"));
return;
}
var robotId = subTask.Task?.RobotId ?? subTask.RobotId ?? Guid.Empty;
try
{
if (robotId != Guid.Empty)
{
var robot = await _robotRepository.GetByIdAsync(robotId, context.CancellationToken);
if (robot != null)
{
_logger.LogInformation("[子任务重新执行] {subTask}清除缓存释放", subTask.Task.TaskCode + "-" + subTask.Sequence);
var protocolService = _protocolServiceFactory.GetService(robot);
await protocolService.CancelRobotTasksAsync(robot);
}
else
{
_logger.LogWarning("[子任务重新执行] 清理VDA路径缓存失败,机器人不存在: RobotId={RobotId}, SubTaskId={SubTaskId}",
robotId, command.SubTaskId);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "[子任务重新执行] 清理VDA路径缓存异常: RobotId={RobotId}, SubTaskId={SubTaskId}",
robotId, command.SubTaskId);
}
// 删除旧子任务,以新SubTaskId重建,确保VDA5050 OrderId唯一性
// EF Core不允许修改被跟踪实体的主键,因此采用删旧建新策略
// @author zzy
var newSubTaskId = Guid.NewGuid();
var oldSubTaskId = subTask.SubTaskId;
await _robotSubTaskRepository.DeleteAsync(subTask, context.CancellationToken);
// await _robotSubTaskRepository.SaveChangesAsync(context.CancellationToken);
var newSubTask = new Domain.Entities.RobotSubTask
{
SubTaskId = newSubTaskId,
TaskId = subTask.TaskId,
RobotId = subTask.RobotId,
BeginNodeId = subTask.BeginNodeId,
EndNodeId = subTask.EndNodeId,
Sequence = subTask.Sequence,
Status = TaskStatus.Pending,
ExecutionCount = 0,
CreatedAt = subTask.CreatedAt,
UpdatedAt = DateTime.Now
};
await _robotSubTaskRepository.AddAsync(newSubTask, context.CancellationToken);
await _robotSubTaskRepository.SaveChangesAsync(context.CancellationToken);
_logger.LogInformation(
"[子任务重新执行] 子任务ID已重建: OldSubTaskId={OldSubTaskId}, NewSubTaskId={NewSubTaskId}, TaskId={TaskId}",
oldSubTaskId, newSubTaskId, subTask.TaskId);
await context.RespondAsync(ApiResponse.Successful("执行成功"));
}
catch (Exception ex)
{
_logger.LogError(ex, "执行子任务失败: SubTaskId={SubTaskId}", command.SubTaskId);
await context.RespondAsync(ApiResponse.Failed(ex.Message));
}
}
}