From 367211f755fe07ad9b894ae1e1845610c9390e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=86=9B?= <2357729423@qq.com> Date: Thu, 21 Mar 2024 09:25:11 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8E=9F=E8=BD=A8?= =?UTF-8?q?=E8=BF=B9=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Events/TrackUpsertEvent.cs | 10 ++++++++++ .../EventHandlers/TrackRefreshEventHandler.cs | 2 ++ .../EventHandlers/TrackUpsertEventHandler.cs | 2 ++ .../TrackDetailsAggregate/TrackDetailsIndex.cs | 5 ----- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs index eb836245..d6fcb03a 100644 --- a/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs @@ -38,4 +38,14 @@ public class TrackUpsertEvent : UpsertTrackInput /// 已经处理过的订单 /// public List Visited { get; set; } = new(); + + /// + /// 原轨迹内容 + /// + public string? OriginTrackContent { get; set; } + + /// + /// 原轨迹报文 + /// + public string? OriginTrackData { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs index 9d0e410d..be24fbf0 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs @@ -95,6 +95,7 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe TrackUpsertEvent @event) { var trackUpsertEvent = @event.DeepCopy(); + trackUpsertEvent.OriginTrackData = JsonConvert.SerializeObject(trackToken); var paramConfig = paramWithContentConfig.ParamConfig; var contentConfigs = paramWithContentConfig.ContentConfigs; TrackPullContentConfigDto? matchedContentConfig = null; @@ -123,6 +124,7 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe var trackContent = trackToken[paramConfig.TrackContentName]?.Value(); if (!trackContent.IsNullOrWhiteSpace()) { + trackUpsertEvent.OriginTrackContent = trackContent; Debug.Assert(trackContent != null, nameof(trackContent) + " != null"); matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentValue == trackContent); diff --git a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs index 48d1d3f9..0e5da045 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs @@ -132,6 +132,8 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe TrackTime = @event.TrackTime!.Value, TrackTimeZone = @event.TrackTimeZone!.Value, IsCanDelete = trackContent.IsCanDelete, + OriginTrackContent = @event.OriginTrackContent, + OriginTrackData = @event.OriginTrackData, CreateUser = CurrentUserRequest.CurrentUser.Name, CreateTime = DateTime.Now }; diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs index 5581c19d..b596c85a 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs @@ -52,11 +52,6 @@ public class TrackDetailsIndex : IdBaseIndex /// public bool IsCompleted { get; set; } - /// - /// 原轨迹状态 - /// - public string? OriginTrackStatus { get; set; } - /// /// 原轨迹内容 /// From 8dcc0596806ff0babd228e2db22d36ccb2d1a9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=86=9B?= <2357729423@qq.com> Date: Thu, 21 Mar 2024 10:00:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?cap=E6=B6=88=E8=B4=B9=E5=B9=82=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EventHandlers/CAPFilter.cs | 109 ++++++++++++++++++ .../SjzyTrackApplicationModule.cs | 9 +- 2 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/SJZY.Track.Application/EventHandlers/CAPFilter.cs diff --git a/src/SJZY.Track.Application/EventHandlers/CAPFilter.cs b/src/SJZY.Track.Application/EventHandlers/CAPFilter.cs new file mode 100644 index 00000000..fbee07b0 --- /dev/null +++ b/src/SJZY.Track.Application/EventHandlers/CAPFilter.cs @@ -0,0 +1,109 @@ +using System.Globalization; +using DotNetCore.CAP.Filter; +using SJZY.Expand.ABP.Core; +using SJZY.Expand.ABP.Core.Logger; +using SJZY.Expand.ABP.Core.PublicMethords; + +namespace SJZY.Track.Application.EventHandlers; + +public class CAPFilter : SubscribeFilter +{ + const string _ERROR_CODE = "Error599"; + + /// + /// 执行前 + /// + /// + /// + public override Task OnSubscribeExecutingAsync(ExecutingContext context) + { + var argumentJsonStr = context.Arguments.ToJson(); + + context.DeliverMessage.Headers["sjzy-receive-time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"); + context.DeliverMessage.Headers["sjzy-arguments"] = argumentJsonStr; + + if (!string.IsNullOrEmpty(argumentJsonStr)) + { + var hash = argumentJsonStr.GetHash(); + using (RedisHelper.Client.Lock("Filter:" + hash, 10)) + { + var isSkip = !string.IsNullOrEmpty(RedisHelper.Client.Get($"CapExcuteFilter:{hash}")); + if (isSkip) + throw new BusinessException(_ERROR_CODE, $"检测到重复消费,消费参数:{argumentJsonStr}"); + + RedisHelper.Client.Set($"CapExcuteFilter:{hash}", 60 * 10, + TimeSpan.FromDays(1).Seconds); // 1天内不允许一模一样的参数重复消费 + } + } + + return Task.CompletedTask; + } + + /// + /// 执行后 + /// + /// + /// + public override Task OnSubscribeExecutedAsync(ExecutedContext context) + { + context.DeliverMessage.Headers.TryGetValue("sjzy-receive-time", out var receiveTime); + context.DeliverMessage.Headers.TryGetValue("cap-msg-name", out var receiveName); + context.DeliverMessage.Headers.TryGetValue("sjzy-arguments", out var arguments); + context.DeliverMessage.Headers.TryGetValue("cap-msg-id", out var messageId); + + BuildLog(receiveTime, receiveName, arguments, false, messageId); + + return Task.CompletedTask; + } + + + /// + /// 消费异常事件 + /// + /// + /// + public override Task OnSubscribeExceptionAsync(ExceptionContext context) + { + context.ExceptionHandled = true; + + if (context.Exception is BusinessException ex && ex.Code == _ERROR_CODE) + LogHelper.Warn(ex.ToString()); + else + LogHelper.Error(context.Exception.ToString()); + + + context.DeliverMessage.Headers.TryGetValue("sjzy-receive-time", out var receiveTime); + context.DeliverMessage.Headers.TryGetValue("cap-msg-id", out var messageId); + context.DeliverMessage.Headers.TryGetValue("cap-msg-name", out var receiveName); + context.DeliverMessage.Headers.TryGetValue("sjzy-arguments", out var arguments); + + BuildLog(receiveTime, receiveName, arguments, true, messageId); + + return Task.CompletedTask; + } + + + private void BuildLog(string receiveTime, string receiveName, string arguments, bool isFromExecptionFliter, + string messageId) + { + var parsedDate = DateTime.ParseExact(receiveTime, "yyyy-MM-dd HH:mm:ss fff", CultureInfo.InvariantCulture); + var useTime = DateTime.Now - parsedDate; + + var log = $@" +|-消息编号:{messageId} +|-消费者名:{receiveName} +|-跳过执行:{(isFromExecptionFliter ? "是" : "否")} +|-执行时间:{receiveTime} +|-消费耗时:{useTime.Milliseconds}毫秒 +|-请求参数:{arguments}"; + + if (useTime.Minutes > 20) + { + LogHelper.Error(log); + } + else + { + //LogHelper.Info(log); + } + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs b/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs index b2b2cd06..88062bb8 100644 --- a/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs +++ b/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs @@ -6,6 +6,7 @@ using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.InterfaceRelay.Application.Contracts; using SJZY.Track.Application.Contract; +using SJZY.Track.Application.EventHandlers; using SJZY.Track.Application.Localization; using SJZY.UserCenter.Contracts; using SJZY.UserCenter.SharedModel; @@ -90,7 +91,7 @@ namespace SJZY.Track.Application { dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached ? "" - : configuration["Swagger:JsonUrlPrefix"]; + : configuration["Swagger:JsonUrlPrefix"]!; }); options.FailedThresholdCallback = faileCalback => { @@ -99,15 +100,15 @@ namespace SJZY.Track.Application LogHelper.Error($@" |-CAP失败回调事件: |-处理类型:{(faileCalback.MessageType == DotNetCore.CAP.Messages.MessageType.Subscribe ? "消费消息达到最大重试次数,需要开发人员介入" : "生产消息推送失败")} - |-头部信息:{faileCalback?.Message?.Headers?.ToJson()} - |-消息内容:{((JsonElement)faileCalback?.Message?.Value).GetRawText()}"); + |-头部信息:{faileCalback.Message.Headers.ToJson()} + |-消息内容:{((JsonElement?)faileCalback.Message.Value)?.GetRawText()}"); } catch (Exception ex) { LogHelper.Error("【严重】CAP失败回调事件发生未处理异常" + ex); } }; - }); + }).AddSubscribeFilter(); } public override void PreConfigureServices(ServiceConfigurationContext context)