Files
Ayay/SHH.CameraService/Core/CommandDispatcher.cs

70 lines
2.8 KiB
C#
Raw Normal View History

2026-01-16 07:23:56 +08:00
using Ayay.SerilogLogs;
using Newtonsoft.Json.Linq;
using Serilog;
2026-01-15 11:04:38 +08:00
using SHH.Contracts.Grpc;
namespace SHH.CameraService;
/// <summary>
/// gRPC 指令分发器
/// 职责:接收从 GrpcCommandReceiverWorker 传入的 Proto 消息,解析参数并路由至具体的 Handler。
/// </summary>
public class CommandDispatcher
{
2026-01-16 07:23:56 +08:00
private static ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc);
2026-01-15 11:04:38 +08:00
private readonly Dictionary<string, ICommandHandler> _handlers;
/// <summary>
/// 构造函数:通过 DI 注入所有已注册的处理器 (SyncCameraHandler, RemoveCameraHandler 等)
/// </summary>
public CommandDispatcher(IEnumerable<ICommandHandler> handlers)
{
// 将处理器列表转换为字典,方便 O(1) 查询
_handlers = handlers.ToDictionary(
h => h.ActionName,
h => h,
StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// 执行指令分发
/// </summary>
/// <param name="protoMsg">从 gRPC Server Streaming 接收到的原始 Proto 指令对象</param>
public async Task DispatchAsync(CommandPayloadProto protoMsg)
{
if (protoMsg == null) return;
string cmdCode = protoMsg.CmdCode; // 例如 "Sync_Camera"
2026-01-16 07:23:56 +08:00
_gRpcLog.Information($"[gRPC] 响应请求, 业务:{protoMsg.CmdCode}, 请求ID:{protoMsg.RequestId}, 业务分发.");
_gRpcLog.Debug($"[gRPC] 响应请求, {protoMsg.CmdCode}, 请求ID:{protoMsg.RequestId}, 业务分发 => {protoMsg}");
2026-01-15 11:04:38 +08:00
try
{
// 1. 查找对应的处理器
if (_handlers.TryGetValue(cmdCode, out var handler))
{
// 2. 参数转换:将 Proto 里的 JSON 字符串转换为原有 Handler 需要的 JToken
// 这样你之前的 SyncCameraHandler 代码不需要做任何逻辑改动即可直接复用
var jsonStr = string.IsNullOrWhiteSpace(protoMsg.JsonParams) ? "{}" : protoMsg.JsonParams;
var token = JToken.Parse(jsonStr);
// 3. 调用具体业务执行
await handler.ExecuteAsync(token);
2026-01-16 07:23:56 +08:00
_gRpcLog.Information($"[gRPC] 业务:{protoMsg.CmdCode}, 请求ID:{protoMsg.RequestId}, 执行成功.");
2026-01-15 11:04:38 +08:00
}
else
{
2026-01-16 07:23:56 +08:00
_gRpcLog.Warning($"[gRPC] 业务:{protoMsg.CmdCode}, 请求ID:{protoMsg.RequestId}, 未找到指令处理器.");
2026-01-15 11:04:38 +08:00
}
}
catch (Exception ex)
{
2026-01-16 07:23:56 +08:00
_gRpcLog.Error($"[gRPC] 业务:{protoMsg.CmdCode}, 请求ID:{protoMsg.RequestId}, 执行指令处理异常: {ex.Message}.");
2026-01-15 11:04:38 +08:00
}
// 注意:关于 ACK (require_ack)
// 在 NetMQ 时代需要手动回发结果,在 gRPC Server Streaming 模式下,
// 建议通过 Unary RPC (例如另设一个 ReportCommandResult 方法) 异步上报执行结果。
}
}