using System.Text; using BSI.Stack.Rabbit; using BSI.Stack.Rabbit.Handler; using Newtonsoft.Json; using RabbitMQ.Client.Events; using SJZY.Expand.ABP.Core.Logger; using SJZY.InterfaceRelay.Application.Contracts; using SJZY.Track.Application.Contract.Dtos.TrackPush; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Application.Helpers; using SJZY.Track.Application.Services.Warning.Handlers; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackPushAggregate; using SJZY.Track.Domain.Enums; using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.Rabbit; public class TrackPushCompletedEventHandler : ITransientDependency, IRabbitHandler { private readonly IOrderRepository _orderRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository; private readonly IBroadcastingService _broadcastingService; private readonly IReturnWarningHandler _returnWarningHandler; public TrackPushCompletedEventHandler(IOrderRepository orderRepository, ITrackPushRecordEsRepository trackPushRecordEsRepository, IBroadcastingService broadcastingService, IReturnWarningHandler returnWarningHandler) { _orderRepository = orderRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository; _broadcastingService = broadcastingService; _returnWarningHandler = returnWarningHandler; } public ConsumeOptions Options() { return new ConsumeOptions { Queue = GlobalConst.TrackPushCompletedSubscribe }; } public async Task Handle(IServiceProvider sp, BasicDeliverEventArgs args, ConsumeOptions options) { var msg = Encoding.UTF8.GetString(args.Body.ToArray()); var @event = System.Text.Json.JsonSerializer.Deserialize(msg); if (@event == null) { LogHelper.Warn( $"rabbit on queue({options.Queue}) received msg can't convert to {nameof(InterfaceRelayForwardReplayEvent)}"); return; } var optionType = Base64Helper.DeSerialize(@event.Attach); var pushInputs = new List(); var updateInputs = new List(); var isAdd = false; // 有多少个订单推送,就有多少个TrackPushInput/TrackUpdateInput返回 // tips:以下处理认为只处理一个单的这次推送的情况 if (optionType == OptionType.新增.ToString()) { pushInputs = JsonConvert.DeserializeObject>(@event.RequestParams)!; isAdd = true; } else if (optionType == OptionType.修改.ToString()) { updateInputs = JsonConvert.DeserializeObject>(@event.RequestParams)!; } var logJsons = pushInputs.Count != 0 ? pushInputs.Select(x => x.Log) : updateInputs.Select(x => x.Log); var logs = new List(pushInputs.Count + updateInputs.Count); foreach (var logJson in logJsons) { if (logJson.IsNullOrEmpty()) throw new InvalidOperationException(); var log = JsonConvert.DeserializeObject(logJson!); if (log == null) throw new BusinessException(message: "轨迹推送返回结果解析异常"); log.IsSuccess = @event.IsSuccess; log.Message = @event.Message; log.RequestId = @event.RequestId; logs.Add(log); } // 推送广播 if (logs.First().IsToMq) _broadcastingService.TrackPushCompletedPublicTopic(logs.Select(BuildDto).ToList()); // 写入推送日志 await _trackPushRecordEsRepository.AddManyAsync(logs); // 同步更新订单主表 await TrackPushAfterUpdateOrderAsync(isAdd, @event.IsSuccess, logs); // todo:引发预警计算 改MQ批量+分流 await _returnWarningHandler.ReceiveTrackPushRecordHandleAsync(@event.IsSuccess, @event.RequestParams, logs, pushInputs, updateInputs); // // 推送广播 // if (log.IsToMq) // _broadcastingService.TrackPushCompletedPublicTopic(BuildDto(log)); // // // 往es 写推送日志 // await _trackPushRecordEsRepository.AddAsync(log); // // // 同步去更新订单主表 // await TrackPushAfterUpdateOrderAsync(log); } private async Task TrackPushAfterUpdateOrderAsync(bool isAdd, bool isSuccess, List logs) { // 修改跳过 if (!isAdd) return; if (!isSuccess) { // 最近一条推送失败 var orders = logs.Select(x => new OrderEntity { Id = x.OrderId, QuestionType = (int) TrackProblemType.Error, LatestPushError = x.Message }).ToList(); await _orderRepository.UpdateRangeAsync(orders, x => new { x.QuestionType, x.LatestPushError }); } else { // 还原成正常态 var orders = logs.Select(x => new OrderEntity { Id = x.OrderId, QuestionType = (int) TrackProblemType.None, LatestPushError = null, LatestPushTrackCode = x.TrackCode, LatestPushTime = x.CreateTime, }).ToList(); await _orderRepository.UpdateRangeAsync(orders, x => new { x.QuestionType, x.LatestPushError, x.LatestPushTrackCode, x.LatestPushTime, }); } } private async Task TrackPushAfterUpdateOrderAsync(TrackPushRecordIndex log) { // tips:只有新增会影响推送进度? if (log.OptionType != OptionType.新增.ToString()) return; var order = new OrderEntity { Id = log.OrderId }; /* * 异常:最近一条推送是失败 */ if (!log.IsSuccess) { order.QuestionType = (int) TrackProblemType.Error; order.LatestPushError = log.Message; await _orderRepository.UpdateColumnAsync(order, x => new { x.QuestionType, x.LatestPushError }); } else { // 还原成正常态 order.QuestionType = (int) TrackProblemType.None; order.LatestPushError = null; order.LatestPushTrackCode = log.TrackCode; order.LatestPushTime = log.CreateTime; await _orderRepository.UpdateColumnAsync(order, x => new { x.LatestPushTrackCode, x.LatestPushTime, x.QuestionType, x.LatestPushError }); } } private TrackPushRecordDto BuildDto(TrackPushRecordIndex log) { return new TrackPushRecordDto { SubSystemCode = log.SubSystemCode, RequestId = log.RequestId, IsSuccess = log.IsSuccess, Message = log.Message, OperationMan = log.CreateUser, PushTime = DateTime.Now, OptionType = log.OptionType, IsManualPush = !string.Equals(log.CreateUser, GlobalConst.SystemUser), //操作人不为系统用户,则认为是人推送 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 }; } }