Merge branch 'S01-轨迹中台' of http://192.168.80.50:3000/Dotnet/SJZY.Track.Api into S01-轨迹中台

This commit is contained in:
moyongzhen 2024-03-06 17:44:37 +08:00
commit 7836a78be6
8 changed files with 70 additions and 33 deletions

View File

@ -16,9 +16,14 @@ public class TrackDeleteEvent
/// 子系统id /// 子系统id
/// </summary> /// </summary>
public int SubSystemId { get; set; } public int SubSystemId { get; set; }
/// <summary> /// <summary>
/// 上游子系统id /// 上游子系统id
/// </summary> /// </summary>
public int UpSubSystemId { get; set; } public int UpSubSystemId { get; set; }
/// <summary>
/// 已经处理过的订单
/// </summary>
public List<int> Visited { get; set; } = new();
} }

View File

@ -1,5 +1,5 @@
using DotNetCore.CAP; using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Expand.ABP.Core.Logger;
using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
@ -8,14 +8,15 @@ using Volo.Abp.DependencyInjection;
namespace SJZY.Track.Application.EventHandlers; namespace SJZY.Track.Application.EventHandlers;
public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
{ {
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly IProvideQueries _provideQueries; private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsRepository _trackDetailsRepository;
private readonly ICapPublisher _capPublisher; 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; _provideQueries = provideQueries;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsRepository = trackDetailsRepository;
@ -26,6 +27,14 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe
[CapSubscribe(GlobalConst.TrackDeleteSubscribe)] [CapSubscribe(GlobalConst.TrackDeleteSubscribe)]
public async Task ConsumerAsync(TrackDeleteEvent @event) 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) if (@event.UpSubSystemId != 0 && @event.UpSubSystemId != @event.SubSystemId)
{ {
@ -40,7 +49,7 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe
@event.TrackCodes = mapCodes; @event.TrackCodes = mapCodes;
} }
await DeleteTrackAsync(@event); await DeleteTrackAsync(@event);
} }
@ -48,7 +57,7 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe
{ {
// 删除轨迹 // 删除轨迹
await _trackDetailsRepository.DeleteTrackAsync(@event.OrderId, @event.TrackCodes); await _trackDetailsRepository.DeleteTrackAsync(@event.OrderId, @event.TrackCodes);
// 根据订单关联关系异步向下刷 // 根据订单关联关系异步向下刷
var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId); var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId);
foreach (var linkedOrder in linkedOrders) foreach (var linkedOrder in linkedOrders)
@ -60,7 +69,7 @@ public class TrackDeleteEventHandler: ITransientDependency, ICapSubscribe
SubSystemId = linkedOrder.SubSystemId, SubSystemId = linkedOrder.SubSystemId,
UpSubSystemId = @event.SubSystemId UpSubSystemId = @event.SubSystemId
}; };
await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, nextEvent); await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, nextEvent);
} }
} }

View File

@ -1,4 +1,5 @@
using DotNetCore.CAP; using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Application.Contract.Services; using SJZY.Track.Application.Contract.Services;
@ -32,7 +33,12 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
[CapSubscribe(GlobalConst.TrackUpsertSubscribe)] [CapSubscribe(GlobalConst.TrackUpsertSubscribe)]
public async Task ConsumerAsync(TrackUpsertEvent @event) 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); @event.Visited.Add(@event.OrderId);
// 不同子系统需要做内容映射 // 不同子系统需要做内容映射
@ -44,7 +50,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
if (mapCode == default) if (mapCode == default)
{ {
//throw new BusinessException(message: "订单跨子系统,未配置内容映射,请联系管理员"); // 跨子系统没做映射的轨迹不处理
return; return;
} }
@ -85,6 +91,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
TrackPlace = @event.TrackPlace, TrackPlace = @event.TrackPlace,
TrackTime = @event.TrackTime!.Value, TrackTime = @event.TrackTime!.Value,
TrackTimeZone = @event.TrackTimeZone!.Value, TrackTimeZone = @event.TrackTimeZone!.Value,
IsCanDelete = trackContent.IsCanDelete,
CreateUser = CurrentUserRequest.CurrentUser.Name, CreateUser = CurrentUserRequest.CurrentUser.Name,
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };

View File

@ -1,7 +1,9 @@
using DotNetCore.CAP; using System.Text.Json;
using DotNetCore.CAP;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using SJZY.Expand.ABP.Core.Localization; using SJZY.Expand.ABP.Core.Localization;
using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.InterfaceRelay.Application.Contracts; using SJZY.InterfaceRelay.Application.Contracts;
using SJZY.Track.Application.Contract; using SJZY.Track.Application.Contract;
using SJZY.Track.Application.Localization; using SJZY.Track.Application.Localization;
@ -70,7 +72,7 @@ namespace SJZY.Track.Application
remoteServiceConfigurationName: "InterfaceForward", remoteServiceConfigurationName: "InterfaceForward",
asDefaultService: false asDefaultService: false
); );
//CAP //CAP
context.Services.AddCapTableNameService(); context.Services.AddCapTableNameService();
context.Services.AddCap(options => context.Services.AddCap(options =>
@ -87,11 +89,24 @@ namespace SJZY.Track.Application
options.FailedRetryCount = 10; options.FailedRetryCount = 10;
options.UseDashboard(dashboardOptions => options.UseDashboard(dashboardOptions =>
{ {
dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached ? "" : configuration["Swagger:JsonUrlPrefix"]; dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached
? ""
: configuration["Swagger:JsonUrlPrefix"];
}); });
options.FailedThresholdCallback = faileCalback => 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);
}
}; };
}); });
} }

View File

@ -76,8 +76,8 @@ public class TrackDetailsIndex : IdBaseIndex
/// </summary> /// </summary>
public float TrackTimeZone { get; set; } public float TrackTimeZone { get; set; }
/// <summary>删除标记 0正常 1 已删除</summary> /// <summary>是否可删</summary>
public bool IsDeleted { get; set; } public bool IsCanDelete { get; set; }
/// <summary>创建人</summary> /// <summary>创建人</summary>
public string? CreateUser { get; set; } public string? CreateUser { get; set; }

View File

@ -16,9 +16,14 @@ public class MatchTrackContentDto
/// 轨迹状态 /// 轨迹状态
/// </summary> /// </summary>
public string Status { get; set; } = null!; public string Status { get; set; } = null!;
/// <summary> /// <summary>
/// 是否意味着完成 /// 是否意味着完成
/// </summary> /// </summary>
public bool IsCompleted { get; set; } public bool IsCompleted { get; set; }
/// <summary>
/// 是否可删
/// </summary>
public bool IsCanDelete { get; set; }
} }

View File

@ -1,6 +1,5 @@
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate; using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackFlagAggregate;
using SJZY.Track.Domain.Aggregates.TrackPullAggregate; using SJZY.Track.Domain.Aggregates.TrackPullAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate; using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate; using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate;
@ -69,14 +68,14 @@ public class ProvideQueries : ISugarRepository, IProvideQueries,
.LeftJoin<TrackTemplateContentEntity>((x, a) => x.TrackTemplateId == a.TrackTemplateId) .LeftJoin<TrackTemplateContentEntity>((x, a) => x.TrackTemplateId == a.TrackTemplateId)
.LeftJoin<TrackContentEntity>((x, a, b) => a.TrackContentId == b.Id) .LeftJoin<TrackContentEntity>((x, a, b) => a.TrackContentId == b.Id)
.LeftJoin<TrackStatusEntity>((x, a, b, c) => b.TrackStatusId == c.Id) .LeftJoin<TrackStatusEntity>((x, a, b, c) => b.TrackStatusId == c.Id)
.LeftJoin<TrackFlagEntity>((x, a, b, c, d) => b.TrackFlagId == d.Id)
.Where((x, a, b) => x.OrderId == orderId && b.Code == code) .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, Content = b.Content,
EnContent = b.EnContent, EnContent = b.EnContent,
Status = c.Status, Status = c.Status,
IsCompleted = b.IsCompleted IsCompleted = b.IsCompleted,
IsCanDelete = a.IsCanDelete
}) })
.FirstAsync(); .FirstAsync();
} }
@ -87,17 +86,18 @@ public class ProvideQueries : ISugarRepository, IProvideQueries,
.LeftJoin<TrackTemplateContentEntity>((x, a) => x.TrackTemplateId == a.TrackTemplateId && a.IsCanDelete) .LeftJoin<TrackTemplateContentEntity>((x, a) => x.TrackTemplateId == a.TrackTemplateId && a.IsCanDelete)
.LeftJoin<TrackContentEntity>((x, a, b) => a.TrackContentId == b.Id) .LeftJoin<TrackContentEntity>((x, a, b) => a.TrackContentId == b.Id)
.Where((x, a, b) => x.OrderId == orderId .Where((x, a, b) => x.OrderId == orderId
&& trackCodes.Contains(b.Code)) && trackCodes.Contains(b.Code) && a.IsCanDelete)
.Select((x, a, b) => b.Code) .Select((x, a, b) => b.Code)
.ToListAsync(); .ToListAsync();
} }
public async Task<List<string>> MapTrackCodesAsync(int upSubSystemId, int subSystemId, params string[] trackCodes) public async Task<List<string>> MapTrackCodesAsync(int upSubSystemId, int subSystemId, params string[] trackCodes)
{ {
// 根据上游code得到下游code
return await Context.Queryable<TrackContentMapEntity>() return await Context.Queryable<TrackContentMapEntity>()
.Where(x => x.SubSystemId == upSubSystemId && x.MapSubSystemId == subSystemId && .Where(x => x.SubSystemId == subSystemId && x.MapSubSystemId == upSubSystemId &&
trackCodes.Contains(x.TrackContentCode)) trackCodes.Contains(x.MapTrackContentCode))
.Select(x => x.MapTrackContentCode) .Select(x => x.TrackContentCode)
.ToListAsync(); .ToListAsync();
} }

View File

@ -20,7 +20,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
.Query(q => .Query(q =>
q.Term(f => f.OrderId, orderId) q.Term(f => f.OrderId, orderId)
&& q.Term(f => f.TrackCode.Suffix("keyword"), trackCode) && q.Term(f => f.TrackCode.Suffix("keyword"), trackCode)
&& q.Term(f => f.IsDeleted, false)
) )
); );
@ -81,7 +80,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
.Field(f => f.OrderNo.Suffix("keyword")) .Field(f => f.OrderNo.Suffix("keyword"))
.Terms(orderNos)) .Terms(orderNos))
&& q.Term(f => f.OrderType, orderType) && q.Term(f => f.OrderType, orderType)
&& q.Term(t => t.Field(f => f.IsDeleted).Value(false))
) )
); );
@ -90,8 +88,9 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
public async Task<List<TrackDetailsIndex>?> GetListAsync(int orderId) public async Task<List<TrackDetailsIndex>?> GetListAsync(int orderId)
{ {
var data = await Context.SearchAsync<TrackDetailsIndex>(x => x.Query(q => q.Term(t => t.OrderId, orderId) var data = await Context.SearchAsync<TrackDetailsIndex>(x => x
&& q.Term(a => a.Field(g => g.IsDeleted).Value(false)) .Query(q =>
q.Term(t => t.OrderId, orderId)
) )
.Size(1000) .Size(1000)
.Sort(s => s.Field(f => f.TrackTime, SortOrder.Descending))); .Sort(s => s.Field(f => f.TrackTime, SortOrder.Descending)));
@ -103,7 +102,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
{ {
var data = await Context.SearchAsync<TrackDetailsIndex>(x => x.Query(q => var data = await Context.SearchAsync<TrackDetailsIndex>(x => x.Query(q =>
q.Terms(t => t.Field(g => g.OrderId).Terms(orderIds)) q.Terms(t => t.Field(g => g.OrderId).Terms(orderIds))
&& q.Term(a => a.Field(d => d.IsDeleted).Value(false))
) )
.Size(10000) .Size(10000)
.Sort(s => s.Field(c => c.TrackTime, SortOrder.Descending)) .Sort(s => s.Field(c => c.TrackTime, SortOrder.Descending))
@ -113,13 +111,12 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
public async Task DeleteTrackAsync(int orderId, List<string> trackCodes) public async Task DeleteTrackAsync(int orderId, List<string> trackCodes)
{ {
var r = await Context.UpdateByQueryAsync<TrackDetailsIndex>(x => x var r = await Context.DeleteByQueryAsync<TrackDetailsIndex>(x => x
.Query( .Query(
q => q =>
q.Term(t => t.OrderId, orderId) q.Term(t => t.OrderId, orderId)
&& q.Term(t => t.IsCanDelete, true)
&& q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))) && q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes)))
.Script(s => s
.Source("ctx._source.isDeleted = true"))
); );
if (!r.IsValid) if (!r.IsValid)
@ -138,7 +135,6 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
q.Terms(t => t q.Terms(t => t
.Field(f => f.OrderNo) .Field(f => f.OrderNo)
.Terms(distinctOrderNumbers)) .Terms(distinctOrderNumbers))
&& q.Term(t => t.Field(f => f.IsDeleted).Value(false))
) )
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)) .Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending))
.From((input.PageIndex - 1) * input.PageSize) .From((input.PageIndex - 1) * input.PageSize)