diff --git a/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs index c88d5837..eccbe955 100644 --- a/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs @@ -16,9 +16,14 @@ public class TrackDeleteEvent /// 子系统id /// public int SubSystemId { get; set; } - + /// /// 上游子系统id /// public int UpSubSystemId { get; set; } + + /// + /// 已经处理过的订单 + /// + public List Visited { get; set; } = new(); } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs index f70492f4..55bb5b1d 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs @@ -1,5 +1,5 @@ using DotNetCore.CAP; -using SJZY.Expand.ABP.Core.PublicMethords; +using SJZY.Expand.ABP.Core.Logger; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; @@ -8,14 +8,15 @@ using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.EventHandlers; -public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe +public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe { private readonly IOrderRepository _orderRepository; private readonly IProvideQueries _provideQueries; private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ICapPublisher _capPublisher; - public TrackDeleteEventHandler(IProvideQueries provideQueries, ITrackDetailsRepository trackDetailsRepository, IOrderRepository orderRepository, ICapPublisher capPublisher) + public TrackDeleteEventHandler(IProvideQueries provideQueries, ITrackDetailsRepository trackDetailsRepository, + IOrderRepository orderRepository, ICapPublisher capPublisher) { _provideQueries = provideQueries; _trackDetailsRepository = trackDetailsRepository; @@ -26,6 +27,14 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe [CapSubscribe(GlobalConst.TrackDeleteSubscribe)] public async Task ConsumerAsync(TrackDeleteEvent @event) { + if (@event.Visited.Contains(@event.OrderId)) + { + LogHelper.Error($"轨迹订单循环依赖预警:{@event.Visited.JoinAsString(",")}"); + return; + } + + @event.Visited.Add(@event.OrderId); + // 不同子系统需要做内容映射 if (@event.UpSubSystemId != 0 && @event.UpSubSystemId != @event.SubSystemId) { @@ -40,7 +49,7 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe @event.TrackCodes = mapCodes; } - + await DeleteTrackAsync(@event); } @@ -48,7 +57,7 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe { // 删除轨迹 await _trackDetailsRepository.DeleteTrackAsync(@event.OrderId, @event.TrackCodes); - + // 根据订单关联关系异步向下刷 var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId); foreach (var linkedOrder in linkedOrders) @@ -60,7 +69,7 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe SubSystemId = linkedOrder.SubSystemId, UpSubSystemId = @event.SubSystemId }; - + await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, nextEvent); } } diff --git a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs index 67eb29a5..29e14bc2 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs @@ -1,4 +1,5 @@ using DotNetCore.CAP; +using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Services; @@ -32,7 +33,12 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe [CapSubscribe(GlobalConst.TrackUpsertSubscribe)] public async Task ConsumerAsync(TrackUpsertEvent @event) { - if (@event.Visited.Contains(@event.OrderId)) return; + if (@event.Visited.Contains(@event.OrderId)) + { + LogHelper.Error($"轨迹订单循环依赖预警:{@event.Visited.JoinAsString(",")}"); + return; + } + @event.Visited.Add(@event.OrderId); // 不同子系统需要做内容映射 @@ -44,7 +50,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe if (mapCode == default) { - //throw new BusinessException(message: "订单跨子系统,未配置内容映射,请联系管理员"); + // 跨子系统没做映射的轨迹不处理 return; } @@ -85,6 +91,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe TrackPlace = @event.TrackPlace, TrackTime = @event.TrackTime!.Value, TrackTimeZone = @event.TrackTimeZone!.Value, + IsCanDelete = trackContent.IsCanDelete, CreateUser = CurrentUserRequest.CurrentUser.Name, CreateTime = DateTime.Now }; diff --git a/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs b/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs index 2bea18a6..ba706085 100644 --- a/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs +++ b/src/SJZY.Track.Application/SjzyTrackApplicationModule.cs @@ -1,7 +1,9 @@ -using DotNetCore.CAP; +using System.Text.Json; +using DotNetCore.CAP; using Microsoft.Extensions.Configuration; using SJZY.Expand.ABP.Core.Localization; 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.Localization; @@ -70,7 +72,7 @@ namespace SJZY.Track.Application remoteServiceConfigurationName: "InterfaceForward", asDefaultService: false ); - + //CAP context.Services.AddCapTableNameService(); context.Services.AddCap(options => @@ -87,11 +89,24 @@ namespace SJZY.Track.Application options.FailedRetryCount = 10; options.UseDashboard(dashboardOptions => { - dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached ? "" : configuration["Swagger:JsonUrlPrefix"]; + dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached + ? "" + : configuration["Swagger:JsonUrlPrefix"]; }); options.FailedThresholdCallback = faileCalback => { - LogHelper.Error($@"{faileCalback.MessageType} 失败了,消息名称: {faileCalback.Message}"); + try + { + LogHelper.Error($@" + |-CAP失败回调事件: + |-处理类型:{(faileCalback.MessageType == DotNetCore.CAP.Messages.MessageType.Subscribe ? "消费消息达到最大重试次数,需要开发人员介入" : "生产消息推送失败")} + |-头部信息:{faileCalback?.Message?.Headers?.ToJson()} + |-消息内容:{((JsonElement)faileCalback?.Message?.Value).GetRawText()}"); + } + catch (Exception ex) + { + LogHelper.Error("【严重】CAP失败回调事件发生未处理异常" + ex); + } }; }); } diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs index 8974dac3..d4f5c9e1 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs @@ -76,8 +76,8 @@ public class TrackDetailsIndex : IdBaseIndex /// public float TrackTimeZone { get; set; } - /// 删除标记 0正常 1 已删除 - public bool IsDeleted { get; set; } + /// 是否可删 + public bool IsCanDelete { get; set; } /// 创建人 public string? CreateUser { get; set; } diff --git a/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs b/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs index 2c2a366d..adb51944 100644 --- a/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs +++ b/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs @@ -16,9 +16,14 @@ public class MatchTrackContentDto /// 轨迹状态 /// public string Status { get; set; } = null!; - + /// /// 是否意味着完成 /// public bool IsCompleted { get; set; } + + /// + /// 是否可删 + /// + public bool IsCanDelete { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs index 119ba0aa..526d5e3d 100644 --- a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs +++ b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs @@ -1,6 +1,5 @@ using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackContentAggregate; -using SJZY.Track.Domain.Aggregates.TrackFlagAggregate; using SJZY.Track.Domain.Aggregates.TrackPullAggregate; using SJZY.Track.Domain.Aggregates.TrackStatusAggregate; using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate; @@ -69,14 +68,14 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, .LeftJoin((x, a) => x.TrackTemplateId == a.TrackTemplateId) .LeftJoin((x, a, b) => a.TrackContentId == b.Id) .LeftJoin((x, a, b, c) => b.TrackStatusId == c.Id) - .LeftJoin((x, a, b, c, d) => b.TrackFlagId == d.Id) .Where((x, a, b) => x.OrderId == orderId && b.Code == code) - .Select((x, a, b, c, d) => new MatchTrackContentDto + .Select((x, a, b, c) => new MatchTrackContentDto { Content = b.Content, EnContent = b.EnContent, Status = c.Status, - IsCompleted = b.IsCompleted + IsCompleted = b.IsCompleted, + IsCanDelete = a.IsCanDelete }) .FirstAsync(); } @@ -87,17 +86,18 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, .LeftJoin((x, a) => x.TrackTemplateId == a.TrackTemplateId && a.IsCanDelete) .LeftJoin((x, a, b) => a.TrackContentId == b.Id) .Where((x, a, b) => x.OrderId == orderId - && trackCodes.Contains(b.Code)) + && trackCodes.Contains(b.Code) && a.IsCanDelete) .Select((x, a, b) => b.Code) .ToListAsync(); } public async Task> MapTrackCodesAsync(int upSubSystemId, int subSystemId, params string[] trackCodes) { + // 根据上游code得到下游code return await Context.Queryable() - .Where(x => x.SubSystemId == upSubSystemId && x.MapSubSystemId == subSystemId && - trackCodes.Contains(x.TrackContentCode)) - .Select(x => x.MapTrackContentCode) + .Where(x => x.SubSystemId == subSystemId && x.MapSubSystemId == upSubSystemId && + trackCodes.Contains(x.MapTrackContentCode)) + .Select(x => x.TrackContentCode) .ToListAsync(); } diff --git a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs index 25dee126..70f62f7e 100644 --- a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs @@ -20,7 +20,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract q.Term(f => f.OrderId, orderId) && q.Term(f => f.TrackCode.Suffix("keyword"), trackCode) - && q.Term(f => f.IsDeleted, false) ) ); @@ -81,7 +80,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract f.OrderNo.Suffix("keyword")) .Terms(orderNos)) && q.Term(f => f.OrderType, orderType) - && q.Term(t => t.Field(f => f.IsDeleted).Value(false)) ) ); @@ -90,8 +88,9 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract?> GetListAsync(int orderId) { - var data = await Context.SearchAsync(x => x.Query(q => q.Term(t => t.OrderId, orderId) - && q.Term(a => a.Field(g => g.IsDeleted).Value(false)) + var data = await Context.SearchAsync(x => x + .Query(q => + q.Term(t => t.OrderId, orderId) ) .Size(1000) .Sort(s => s.Field(f => f.TrackTime, SortOrder.Descending))); @@ -103,7 +102,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract(x => x.Query(q => q.Terms(t => t.Field(g => g.OrderId).Terms(orderIds)) - && q.Term(a => a.Field(d => d.IsDeleted).Value(false)) ) .Size(10000) .Sort(s => s.Field(c => c.TrackTime, SortOrder.Descending)) @@ -113,13 +111,12 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract trackCodes) { - var r = await Context.UpdateByQueryAsync(x => x + var r = await Context.DeleteByQueryAsync(x => x .Query( q => q.Term(t => t.OrderId, orderId) + && q.Term(t => t.IsCanDelete, true) && q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))) - .Script(s => s - .Source("ctx._source.isDeleted = true")) ); if (!r.IsValid) @@ -138,7 +135,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract t .Field(f => f.OrderNo) .Terms(distinctOrderNumbers)) - && q.Term(t => t.Field(f => f.IsDeleted).Value(false)) ) .Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)) .From((input.PageIndex - 1) * input.PageSize)