using System.Text; using Fake.RabbitMQ; using InterfaceForward.Domain.Shared.Helpers; using RabbitMQ.Client; using TrackCenter.Application.Dtos.TrackPush; using TrackCenter.Application.Events; namespace TrackCenter.Application.Services.Broadcasting; /// /// 对外 Topic 广播(下游仍按 Newtonsoft PascalCase 契约消费,不经 Messaging 信封)。 /// public class BroadcastingService(IRabbitMqChannelPool channelPool) : ITransientDependency { public void TrackChangePublicTopic(TrackChangeEto eto, string AppCode) { PublishByConfirmSelect( GlobalConst.TrackChangeExchange, ExchangeType.Topic, $"TrackChange.{AppCode}", Encoding.UTF8.GetBytes(eto.ToJson()), prop => { prop.Persistent = true; }); } /// /// 轨迹推送完成广播(批量) /// public void TrackPushCompletedPublicTopic(List list) { var data = list .Select(TrackPushRecordDtoToEvent) .Select(x => Encoding.UTF8.GetBytes(x.ToJson())); var log = list.First(); PublishByConfirmSelect( GlobalConst.TrackPushExchange, ExchangeType.Topic, $"TrackPush.{log.AppKey}", data, prop => { prop.Persistent = true; }); } /// /// 轨迹推送完成广播 /// public void TrackPushCompletedPublicTopic(TrackPushRecordDto log) { var data = TrackPushRecordDtoToEvent(log); PublishByConfirmSelect( GlobalConst.TrackPushExchange, ExchangeType.Topic, $"TrackPush.{log.AppKey}", Encoding.UTF8.GetBytes(data.ToJson()), prop => { prop.Persistent = true; }); } /// /// 轨迹推送失败广播 /// public void TrackPushFailedPubilcTopic(TrackPushRecordDto log) { //暂时使用推送完成模型,后续可能会出现有区分度的模型 TrackPushCompletedPublicTopic(log); } private void PublishByConfirmSelect( string exchange, string exchangeType, string routingKey, byte[] data, Action? options = null) { using var channelAccessor = channelPool.Acquire(routingKey); var channel = channelAccessor.Channel; channel.ExchangeDeclare(exchange, exchangeType, durable: true); var props = channel.CreateBasicProperties(); options?.Invoke(props); channel.ConfirmSelect(); channel.BasicPublish(exchange, routingKey, props, data); channel.WaitForConfirmsOrDie(); } private void PublishByConfirmSelect( string exchange, string exchangeType, string routingKey, IEnumerable datas, Action? options = null) { using var channelAccessor = channelPool.Acquire(routingKey); var channel = channelAccessor.Channel; channel.ExchangeDeclare(exchange, exchangeType, durable: true); var props = channel.CreateBasicProperties(); options?.Invoke(props); channel.ConfirmSelect(); foreach (var data in datas) channel.BasicPublish(exchange, routingKey, props, data); channel.WaitForConfirmsOrDie(); } private static TrackPushCompletedEvent TrackPushRecordDtoToEvent(TrackPushRecordDto log) { return new TrackPushCompletedEvent { RequestId = log.RequestId, IsSuccess = log.IsSuccess, Message = log.Message, OperationMan = log.OperationMan, PushTime = log.PushTime, OptionType = log.OptionType, IsManualPush = log.IsManualPush, //操作人不为系统用户,则认为是人推送 PushContent = log.PushContent, OrderNo = log.OrderNo, TrackStatus = log.TrackStatus, TrackContent = log.TrackContent, TrackTimeZone = log.TrackTimeZone, TrackTime = log.TrackTime, TrackPlace = log.TrackPlace, TrackCode = log.TrackCode, Extra = log.Extra, InterfaceRelayData = log.InterfaceRelayData }; } }