opt:优化轨迹upsert流程

This commit is contained in:
李鹏军 2024-03-26 17:31:50 +08:00
parent f85bc95e19
commit b232d96634
9 changed files with 136 additions and 47 deletions

View File

@ -1,14 +1,22 @@
using SJZY.Track.Application.Contract.Dtos.ProvideServices; namespace SJZY.Track.Application.Contract.Events;
namespace SJZY.Track.Application.Contract.Events; public class TrackUpsertEvent
public class TrackUpsertEvent : UpsertTrackInput
{ {
/// <summary> /// <summary>
/// 订单id /// 订单id
/// </summary> /// </summary>
public int OrderId { get; set; } public int OrderId { get; set; }
/// <summary>
/// 订单类型
/// </summary>
public int OrderType { get; set; }
/// <summary>
/// 订单号
/// </summary>
public string OrderNo { get; set; } = null!;
/// <summary> /// <summary>
/// 订单是否完成 /// 订单是否完成
/// </summary> /// </summary>
@ -34,11 +42,6 @@ public class TrackUpsertEvent : UpsertTrackInput
/// </summary> /// </summary>
public int UpSubSystemId { get; set; } public int UpSubSystemId { get; set; }
/// <summary>
/// 已经处理过的订单
/// </summary>
public List<int> Visited { get; set; } = new();
/// <summary> /// <summary>
/// 原轨迹内容 /// 原轨迹内容
/// </summary> /// </summary>
@ -53,4 +56,34 @@ public class TrackUpsertEvent : UpsertTrackInput
/// 操作人 /// 操作人
/// </summary> /// </summary>
public string? OperationMan { get; set; } public string? OperationMan { get; set; }
/// <summary>
/// true新增,false更新,null表示刷新引发的新增/更新
/// </summary>
public bool? IsAdd { get; set; }
/// <summary>
/// 轨迹内容代码
/// </summary>
public string TrackCode { get; set; } = null!;
/// <summary>
/// 轨迹发生地
/// </summary>
public string TrackPlace { get; set; } = null!;
/// <summary>
/// 轨迹发生时间
/// </summary>
public DateTime TrackTime { get; set; }
/// <summary>
/// 轨迹发生时区
/// </summary>
public float TrackTimeZone { get; set; }
/// <summary>
/// 已经处理过的订单
/// </summary>
public List<int> Visited { get; set; } = new();
} }

View File

@ -5,7 +5,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
<Version>1.0.0</Version> <Version>1.0.1</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -65,15 +65,15 @@ public class CAPFilter : SubscribeFilter
public override Task OnSubscribeExceptionAsync(ExceptionContext context) public override Task OnSubscribeExceptionAsync(ExceptionContext context)
{ {
context.ExceptionHandled = true; context.ExceptionHandled = true;
context.DeliverMessage.Headers.TryGetValue("cap-msg-id", out var messageId);
if (context.Exception is BusinessException ex && ex.Code == _ERROR_CODE) if (context.Exception is BusinessException ex && ex.Code == _ERROR_CODE)
LogHelper.Warn(ex.ToString()); LogHelper.Warn(ex.ToString());
else else
LogHelper.Error(context.Exception.ToString()); LogHelper.Error($"cap-msg-id:{messageId}\n{context.Exception}");
context.DeliverMessage.Headers.TryGetValue("sjzy-receive-time", out var receiveTime); 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("cap-msg-name", out var receiveName);
context.DeliverMessage.Headers.TryGetValue("sjzy-arguments", out var arguments); context.DeliverMessage.Headers.TryGetValue("sjzy-arguments", out var arguments);
@ -89,16 +89,15 @@ public class CAPFilter : SubscribeFilter
var parsedDate = DateTime.ParseExact(receiveTime, "yyyy-MM-dd HH:mm:ss fff", CultureInfo.InvariantCulture); var parsedDate = DateTime.ParseExact(receiveTime, "yyyy-MM-dd HH:mm:ss fff", CultureInfo.InvariantCulture);
var useTime = DateTime.Now - parsedDate; var useTime = DateTime.Now - parsedDate;
var log = $@" if (useTime.Minutes > 20)
{
var log = $@"
|-消息编号:{messageId} |-消息编号:{messageId}
|-消费者名:{receiveName} |-消费者名:{receiveName}
|-跳过执行:{(isFromExecptionFliter ? "是" : "否")} |-跳过执行:{(isFromExecptionFliter ? "是" : "否")}
|-执行时间:{receiveTime} |-执行时间:{receiveTime}
|-消费耗时:{useTime.Milliseconds}毫秒 |-消费耗时:{useTime.Milliseconds}毫秒
|-请求参数:{arguments}"; |-请求参数:{arguments}";
if (useTime.Minutes > 20)
{
LogHelper.Error(log); LogHelper.Error(log);
} }
else else

View File

@ -158,7 +158,7 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe
} }
} }
if (matchedContentConfig is null) return; // if (matchedContentConfig is null) return;
// 轨迹发生地 // 轨迹发生地
var trackPlace = paramConfig.TrackPlaceName == null var trackPlace = paramConfig.TrackPlaceName == null
@ -167,7 +167,7 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe
if (trackPlace.IsNullOrWhiteSpace()) if (trackPlace.IsNullOrWhiteSpace())
{ {
Expression<Func<OrderEntity, string?>> resultExpression = Expression<Func<OrderEntity, string?>> resultExpression =
(TrackLocationValue?)matchedContentConfig.TrackPlaceValue switch (TrackLocationValue?)matchedContentConfig?.TrackPlaceValue switch
{ {
TrackLocationValue.ArrivalPort => x => x.ArrivalPort, TrackLocationValue.ArrivalPort => x => x.ArrivalPort,
TrackLocationValue.ArriveCity => x => x.ArrivalCity, TrackLocationValue.ArriveCity => x => x.ArrivalCity,
@ -191,10 +191,10 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe
: trackToken[paramConfig.TrackTimeZoneName]?.Value<float>(); : trackToken[paramConfig.TrackTimeZoneName]?.Value<float>();
// 新增/更新轨迹 // 新增/更新轨迹
trackUpsertEvent.TrackCode = matchedContentConfig.TrackContentCode; trackUpsertEvent.TrackCode = matchedContentConfig?.TrackContentCode ?? GlobalConst.EmptyString;
trackUpsertEvent.TrackPlace = trackPlace ?? "CN"; trackUpsertEvent.TrackPlace = trackPlace ?? GlobalConst.EmptyString;
trackUpsertEvent.TrackTime = trackTime ?? DateTime.Now; trackUpsertEvent.TrackTime = trackTime ?? DateTime.Now;
trackUpsertEvent.TrackTimeZone = trackTimeZone ?? matchedContentConfig.TrackTimeZoneValue ?? 8; trackUpsertEvent.TrackTimeZone = trackTimeZone ?? matchedContentConfig?.TrackTimeZoneValue ?? 8;
await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, trackUpsertEvent); await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, trackUpsertEvent);
} }
} }

View File

@ -40,6 +40,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
return; return;
} }
var isUnProcessed = false;
// 不同子系统需要做内容映射 // 不同子系统需要做内容映射
if (@event.UpSubSystemId != 0 && @event.UpSubSystemId != @event.SubSystemId) if (@event.UpSubSystemId != 0 && @event.UpSubSystemId != @event.SubSystemId)
{ {
@ -56,13 +57,22 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
@event.TrackCode = mapCode; @event.TrackCode = mapCode;
} }
var track = await _trackDetailsRepository.GetFirstOrDefaultAsync(@event.OrderId, @event.TrackCode); var track = @event.TrackCode == GlobalConst.EmptyString
if (track == null && !@event.IsAdd) return; ? await _trackDetailsRepository.GetFirstOrDefaultAsync(@event.OrderId, @event.TrackTime)
if (track != null && @event.IsAdd) return; : await _trackDetailsRepository.GetFirstOrDefaultAsync(@event.OrderId, @event.TrackCode);
if (@event.TrackCode == GlobalConst.EmptyString && track != null) return; // 无法映射的轨迹只做新增
if (@event.IsAdd != null) // 手动操作需要做区分
{
if (track == null && !@event.IsAdd!.Value) return; // 不存在不让改
if (track != null && @event.IsAdd!.Value) return; // 存在不让创建
}
// step1、upsert es轨迹 // step1、upsert es轨迹
track = await UpsertTrackAsync(track, @event); track = await UpsertTrackAsync(track, @event);
if (track == null) return; // 模板没配该轨迹代码,无法入库
if (track == null || @event.TrackCode == GlobalConst.EmptyString) return; // 模板没配该轨迹代码,不再继续
// step2、触发轨迹推送事件(异步) // step2、触发轨迹推送事件(异步)
await HandleTrackPushAsync(@event, track); await HandleTrackPushAsync(@event, track);
@ -107,44 +117,64 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
{ {
if (track == default) if (track == default)
{ {
//todo:可以优化
// 根据轨迹code在订单模板内容中寻找匹配的
var trackContent = await _provideQueries.MatchTrackContentAsync(@event.OrderId, @event.TrackCode);
if (trackContent == default)
{
// 订单所绑定的模板,没有一条内容可以匹配发生的轨迹
return null;
}
track = new TrackDetailsIndex track = new TrackDetailsIndex
{ {
IndexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}", IndexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}",
OrderId = @event.OrderId, OrderId = @event.OrderId,
OrderNo = @event.OrderNo, OrderNo = @event.OrderNo,
OrderType = @event.OrderType, OrderType = @event.OrderType,
TrackStatus = trackContent.Status,
TrackCode = @event.TrackCode, TrackCode = @event.TrackCode,
TrackContent = trackContent.Content,
TrackContentId = trackContent.Id,
IsCompleted = trackContent.IsCompleted,
TrackEnContent = trackContent.EnContent,
TrackPlace = @event.TrackPlace, TrackPlace = @event.TrackPlace,
TrackTime = @event.TrackTime!.Value, TrackTime = @event.TrackTime,
TrackTimeZone = @event.TrackTimeZone!.Value, TrackTimeZone = @event.TrackTimeZone,
IsCanDelete = trackContent.IsCanDelete, IsCanDelete = false,
OriginTrackContent = @event.OriginTrackContent, OriginTrackContent = @event.OriginTrackContent,
OriginTrackData = @event.OriginTrackData, OriginTrackData = @event.OriginTrackData,
CreateUser = @event.OperationMan, CreateUser = @event.OperationMan,
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };
track.ZeroTrackTime = track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); // tips:刷新到无法匹配内容的轨迹引起的插入
if (@event.TrackCode == GlobalConst.EmptyString)
{
track.TrackStatus = GlobalConst.EmptyString;
track.TrackContent = GlobalConst.EmptyString;
track.TrackContentId = 0;
track.IsCompleted = false;
track.TrackEnContent = GlobalConst.EmptyString;
}
else
{
//todo:可以优化
// 根据轨迹code在订单模板内容中寻找匹配的
var trackContent = await _provideQueries.MatchTrackContentAsync(@event.OrderId, @event.TrackCode);
if (trackContent == default)
{
// 订单所绑定的模板,没有一条内容可以匹配发生的轨迹
return null;
}
track = new TrackDetailsIndex
{
TrackStatus = trackContent.Status,
TrackContent = trackContent.Content,
TrackContentId = trackContent.Id,
IsCompleted = trackContent.IsCompleted,
TrackEnContent = trackContent.EnContent,
IsCanDelete = trackContent.IsCanDelete
};
track.ZeroTrackTime = track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone));
}
} }
else else
{ {
// tips:刷新到无法匹配内容的轨迹 相同的发生时间不做更新处理
if (@event.TrackCode == GlobalConst.EmptyString) return track;
track.TrackPlace = @event.TrackPlace; track.TrackPlace = @event.TrackPlace;
track.TrackTime = @event.TrackTime!.Value; track.TrackTime = @event.TrackTime;
track.TrackTimeZone = @event.TrackTimeZone!.Value; track.TrackTimeZone = @event.TrackTimeZone;
track.UpdateUser = @event.OperationMan ?? "系统"; track.UpdateUser = @event.OperationMan ?? "系统";
track.UpdateTime = DateTime.Now; track.UpdateTime = DateTime.Now;
} }

View File

@ -91,8 +91,8 @@ public partial class TrackService : ApplicationService, ITrackService
IsAdd = input.IsAdd, IsAdd = input.IsAdd,
TrackCode = input.TrackCode, TrackCode = input.TrackCode,
TrackPlace = input.TrackPlace, TrackPlace = input.TrackPlace,
TrackTime = input.TrackTime, TrackTime = input.TrackTime!.Value,
TrackTimeZone = input.TrackTimeZone, TrackTimeZone = input.TrackTimeZone!.Value,
OrderType = input.OrderType, OrderType = input.OrderType,
OrderNo = order.OrderNo, OrderNo = order.OrderNo,
OrderId = order.Id, OrderId = order.Id,

View File

@ -6,6 +6,8 @@ public interface ITrackDetailsRepository
{ {
Task<TrackDetailsIndex?> GetFirstOrDefaultAsync(int orderId, string trackCode); Task<TrackDetailsIndex?> GetFirstOrDefaultAsync(int orderId, string trackCode);
Task<TrackDetailsIndex?> GetFirstOrDefaultAsync(int orderId, DateTime trackTime);
Task UpsertAsync(TrackDetailsIndex index); Task UpsertAsync(TrackDetailsIndex index);
Task<List<TrackDetailsIndex>> GetListAsync(int orderType, List<string> orderNos); Task<List<TrackDetailsIndex>> GetListAsync(int orderType, List<string> orderNos);

View File

@ -0,0 +1,6 @@
namespace SJZY.Track.Domain.Consts;
public partial class GlobalConst
{
public const string EmptyString = "--";
}

View File

@ -32,6 +32,25 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
return res; return res;
} }
public async Task<TrackDetailsIndex?> GetFirstOrDefaultAsync(int orderId, DateTime trackTime)
{
var r = await Context.SearchAsync<TrackDetailsIndex>(s => s
.Source()
.Query(q =>
q.Term(f => f.OrderId, orderId)
&& q.Term(f => f.TrackTime, trackTime)
)
);
var res = r.Documents.FirstOrDefault();
if (res != default && r.Hits.FirstOrDefault() != default)
{
res.Id = r.Hits.FirstOrDefault()!.Id;
}
return res;
}
public async Task UpsertAsync(TrackDetailsIndex index) public async Task UpsertAsync(TrackDetailsIndex index)
{ {
if (index.Id.IsNullOrWhiteSpace()) if (index.Id.IsNullOrWhiteSpace())