diff --git a/src/SJZY.Track.Application.Contract/Dtos/Forewarning/WarningNotifyCacheEntry.cs b/src/SJZY.Track.Application.Contract/Dtos/Forewarning/WarningNotifyCacheEntry.cs
index 591be62e..835d3aea 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/Forewarning/WarningNotifyCacheEntry.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/Forewarning/WarningNotifyCacheEntry.cs
@@ -14,6 +14,7 @@ public class WarningNotifyCacheEntry
var values = notifyValue.Split('_');
RuleId = int.Parse(values[0]);
OrderId = int.Parse(values[1]);
+ Counter = int.Parse(values[2]);
}
///
diff --git a/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs b/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs
index 14647fcc..07b792ac 100644
--- a/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs
+++ b/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs
@@ -18,5 +18,5 @@ public interface IForewarningNotifyService
///
/// 发送通知。
///
- Task SendNotificationAsync(int subSystemId);
+ Task SendNotificationAsync(int subSystemId);
}
diff --git a/src/SJZY.Track.Application/BackgroundServices/OrderPullStatusScanner.cs b/src/SJZY.Track.Application/BackgroundServices/OrderPullStatusScanner.cs
new file mode 100644
index 00000000..943ddbe7
--- /dev/null
+++ b/src/SJZY.Track.Application/BackgroundServices/OrderPullStatusScanner.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.Hosting;
+using SJZY.Expand.ABP.Core.Logger;
+using SJZY.Track.Domain.Aggregates.OrderAggregate;
+
+namespace SJZY.Track.Application.BackgroundServices;
+
+public class OrderPullStatusScanner : BackgroundService
+{
+ private readonly IOrderRepository _orderRepository;
+
+ public OrderPullStatusScanner(IOrderRepository orderRepository)
+ {
+ _orderRepository = orderRepository;
+ }
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ var count = await _orderRepository.UpdatePullStatusBySilenceAsync();
+ if (count > 0)
+ {
+ LogHelper.Info($"{nameof(OrderPullStatusScanner)}本次扫描更新了{count}条订单的拉取状态");
+ }
+
+ await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
+ }
+}
diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/PushWarningEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/PushWarningEventHandler.cs
deleted file mode 100644
index dac2576e..00000000
--- a/src/SJZY.Track.Application/CAP/EventHandlers/PushWarningEventHandler.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using DotNetCore.CAP;
-using Microsoft.Extensions.Logging;
-using SJZY.Expand.ABP.Core;
-using SJZY.Track.Application.Contract.Events;
-using SJZY.Track.Domain.Aggregates.OrderAggregate;
-using Volo.Abp.DependencyInjection;
-
-namespace SJZY.Track.Application.CAP.EventHandlers;
-
-public class PushWarningEventHandler : ITransientDependency, ICapSubscribe
-{
- private readonly ILogger _logger;
- private readonly IOrderRepository _orderRepository;
-
- public PushWarningEventHandler(IOrderRepository orderRepository,
- ILogger logger)
- {
- _orderRepository = orderRepository;
- _logger = logger;
- }
-
- [CapSubscribe(GlobalConst.TrackPushWarning)]
- public async Task Handle(PushWarningEvent @event)
- {
- var hasProcess = await RedisHelper.Client.ExistsAsync(GlobalConst.TrackPushTrackWaringLockKey);
- if (hasProcess)
- {
- return;
- }
-
- await RedisHelper.Client.SetAsync(GlobalConst.TrackPushTrackWaringLockKey, 1, TimeSpan.FromHours(3));
-
- int total = 0, pageSize = @event.PageSize, waitTime = 1000;
- var rows = 0;
- var pageindex = 0;
-
- do
- {
- rows = await _orderRepository.PushWarnOrdersAsync(pageSize, pageindex);
- pageindex++;
- total += rows;
- await Task.Delay(waitTime);
- } while (rows == pageSize);
-
- await RedisHelper.Client.DelAsync(GlobalConst.TrackPushTrackWaringLockKey);
- _logger.LogInformation(message: "本次预警扫描了:{total}个订单", total);
- }
-}
diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/TrackUpsertEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackUpsertEventHandler.cs
index 5d5583e3..940a2c66 100644
--- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackUpsertEventHandler.cs
+++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackUpsertEventHandler.cs
@@ -196,8 +196,15 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
if (canNextOrderIds.Count == 0) return;
- // 批量add to es
- await _trackDetailsEsRepository.AddManyAsync(insertTracks);
+ if (tracks.Any())
+ {
+ // 批量add to es
+ await _trackDetailsEsRepository.AddManyAsync(insertTracks);
+
+ // add track触发订单拉取状态更新
+ await _orderRepository.UpdatePullStatusToSilenceAsync(insertTracks.Select(x => x.OrderId).ToList(),
+ @event.TrackCode);
+ }
// 触发订单主表更新事件(异步)
await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe,
diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs
index 4f104e7d..d51fee1b 100644
--- a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs
+++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs
@@ -99,7 +99,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
await _warningRecordEsRepository.BulkUpdateAsync(dels); // 标记处理完成
}
- public async Task SendNotificationAsync(int subSystemId)
+ public async Task SendNotificationAsync(int subSystemId)
{
var redisKey = GetForewarningNotifySetKeyRedisKey(subSystemId);
var timestamp = GetTimestamp(DateTime.Now);
@@ -108,7 +108,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
if (set.IsNullOrEmpty())
{
LogHelper.Info("没有运输时效需要预警");
- return;
+ return 0;
}
var entries = set.Select(x => new WarningNotifyCacheEntry(x)).ToList();
@@ -142,6 +142,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
CustomName = rule.CustomName,
RuleId = entry.RuleId,
Rule = rule.ToString(),
+ Counter = entry.Counter,
OrderId = entry.OrderId,
WarningStatus = WarningStatus.UnProcessed,
NotifyUser = rule.NotifyUser,
@@ -170,6 +171,8 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
}
await RedisHelper.Client.ZRemRangeByScoreAsync(redisKey, 0, timestamp);
+
+ return warningRecords.Count;
}
private string GetForewarningNotifySetKeyRedisKey(int subSystemId) =>
diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs
index 421026e4..377edd93 100644
--- a/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs
+++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs
@@ -91,8 +91,12 @@ public class TrackPullService : ApplicationService
public async Task RefreshForTaskAsync()
{
var configs = await _trackPullCacheService.GetAllPullConfigsAsync();
- var tasks = configs.Select(RefreshForConfigAsync).ToArray();
- await Task.WhenAll(tasks);
+
+ foreach (var config in configs)
+ {
+ await RefreshForConfigAsync(config);
+ }
+
return true;
}
@@ -122,38 +126,50 @@ public class TrackPullService : ApplicationService
return;
}
- var page = 1;
- var orders = await _provideQueries.FindOrderWithServiceProviderAsync(config.ServiceProviderId, page);
- while (orders.Any())
+ _ = Task.Run(async () =>
{
- var serviceProviderCode = orders.FirstOrDefault()?.ServiceProviderCode;
- var serviceProviderName = orders.FirstOrDefault()?.ServiceProviderName;
-
- foreach (var group in orders.GroupBy(x => new
+ try
{
- x.SubSystemId,
- x.OrderType
- }))
- {
- var data = new List
public const string TrackChangeAfterUpdateOrderSubscribe = "SJZY.Track.TrackChangeAfterUpdateOrder";
- ///
- /// 推送预警任务
- ///
- public const string TrackPushWarning = "SJZY.Track.TrackPushWarning";
-
///
/// 预警计算任务
///
diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/GetOrderWarningPageOutput.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/GetOrderWarningPageOutput.cs
index e1fede89..511e2cbc 100644
--- a/src/SJZY.Track.Domain/Dtos/Forewarning/GetOrderWarningPageOutput.cs
+++ b/src/SJZY.Track.Domain/Dtos/Forewarning/GetOrderWarningPageOutput.cs
@@ -19,6 +19,11 @@ public class GetOrderWarningPageOutput
///
public string Rule { get; set; } = null!;
+ ///
+ /// 预警次数
+ ///
+ public int Counter { get; set; }
+
///
/// 预警状态
///
diff --git a/src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs b/src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs
index 4e328abb..14a9d15b 100644
--- a/src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs
+++ b/src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs
@@ -1,3 +1,5 @@
+using SJZY.Track.Domain.Aggregates.OrderAggregate;
+
namespace SJZY.Track.Domain.Dtos.Order;
public class OrderWithServiceProviderVO
@@ -23,4 +25,9 @@ public class OrderWithServiceProviderVO
/// 子系统id
///
public int SubSystemId { get; set; }
+
+ ///
+ /// 轨迹拉取状态
+ ///
+ public TrackPullStatus TrackPullStatus { get; set; }
}
diff --git a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs
index 05d41256..c23394d9 100644
--- a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs
+++ b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs
@@ -58,14 +58,16 @@ public class ProvideQueries : ISugarRepository, IProvideQueries,
return await Context.Queryable()
.RightJoin((a, b) => a.Id == b.OrderId)
.LeftJoin((a, b, c) => b.ServiceProviderCode == c.Code)
- .Where((a, b, c) => c.Id == serviceProviderId && !a.IsCompleted)
+ .Where((a, b, c) => c.Id == serviceProviderId && !a.IsCompleted
+ && b.StartTime <= DateTime.Now && b.EndTime >= DateTime.Now)
.Select((a, b, c) => new OrderWithServiceProviderVO
{
OrderNo = a.OrderNo,
OrderType = a.OrderType,
ServiceProviderCode = c.Code,
ServiceProviderName = c.Name,
- SubSystemId = a.SubSystemId
+ SubSystemId = a.SubSystemId,
+ TrackPullStatus = b.PullStatus
})
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
diff --git a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs
index e7517f86..98594ff0 100644
--- a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs
+++ b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs
@@ -1,3 +1,4 @@
+using SJZY.Expand.ABP.Core.Logger;
using SJZY.Track.Domain;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Dtos.Order;
@@ -120,9 +121,7 @@ public class OrderRepository : BasicRepository, IOrderRepository, I
public async Task PushWarnOrdersAsync(int pageSize, int pageindex)
{
var ordersToUpdate = await Context.Queryable()
- .Where(b => !b.IsCompleted
- && b.QuestionType != 1
- && !b.IsDeleted)
+ .Where(b => !b.IsCompleted && b.QuestionType != 1)
.Select(b => new
{
b.LatestPushTime,
@@ -162,6 +161,73 @@ public class OrderRepository : BasicRepository, IOrderRepository, I
return res.Select(x => (x.Key, x.Id)).ToList();
}
+ public async Task UpdatePullStatusToSilenceAsync(List orderIds, string trackCode)
+ {
+ // var status = await Context.Queryable()
+ // .Where(x => orderIds.Contains(x.OrderId) && x.StartTrackCode == trackCode)
+ // .Where(x => x.PullStatus == TrackPullStatus.Init || x.PullStatus == TrackPullStatus.Pulling)
+ // .Select(x => new
+ // {
+ // x.Id,
+ // x.PullStatus,
+ // x.SilenceBeforeStart,
+ // x.SilenceAfterEnd,
+ // x.StartTime,
+ // x.EndTime
+ // })
+ // .ToListAsync();
+ //
+ // // 初始态-》静默前、拉取中-》静默后
+ // var changes = status.Select(x => new
+ // {
+ // x.Id,
+ // PullStatus = x.PullStatus == TrackPullStatus.Init
+ // ? x.SilenceBeforeStart > 0
+ // ? TrackPullStatus.SilenceBeforeStart
+ // : TrackPullStatus.Pulling
+ // : x.SilenceAfterEnd > 0
+ // ? TrackPullStatus.SilenceAfterEnd
+ // : TrackPullStatus.Completed,
+ // StartTime =
+ // x.PullStatus == TrackPullStatus.Init ? DateTime.Now.AddHours(x.SilenceBeforeStart) : x.StartTime,
+ // EndTime = x.PullStatus == TrackPullStatus.Pulling ? DateTime.Now.AddHours(x.SilenceAfterEnd) : x.EndTime
+ // });
+ // await Context.Updateable(changes).ExecuteCommandAsync();
+
+ // 初始态-》静默前
+ await Context.Updateable()
+ .SetColumns(x => x.PullStatus == TrackPullStatus.SilenceBeforeStart)
+ .SetColumns(x => x.StartTime == DateTime.Now.AddHours(x.SilenceBeforeStart))
+ .Where(x => orderIds.Contains(x.OrderId) && x.StartTrackCode == trackCode)
+ .Where(x => x.PullStatus == TrackPullStatus.Init)
+ .ExecuteCommandAsync();
+
+ // 拉取中-》静默后
+ await Context.Updateable()
+ .SetColumns(x => x.PullStatus == TrackPullStatus.SilenceAfterEnd)
+ .SetColumns(x => x.EndTime == DateTime.Now.AddHours(x.SilenceAfterEnd)) // >0才有意义
+ .Where(x => orderIds.Contains(x.OrderId) && x.EndTrackCode == trackCode)
+ .Where(x => x.PullStatus == TrackPullStatus.Pulling)
+ .ExecuteCommandAsync();
+ }
+
+ public async Task UpdatePullStatusBySilenceAsync()
+ {
+ var cnt1 = await Context.Updateable()
+ .SetColumns(x => x.PullStatus == TrackPullStatus.Pulling)
+ .Where(x => x.PullStatus == TrackPullStatus.SilenceBeforeStart && x.StartTime > DateTime.Now)
+ .ExecuteCommandAsync();
+ LogHelper.Info($"{cnt1}条订单的拉取状态由SilenceBeforeStart更新为Pulling");
+
+ var cnt2 = await Context.Updateable()
+ .SetColumns(x => x.PullStatus == TrackPullStatus.Completed)
+ .Where(x => x.PullStatus == TrackPullStatus.SilenceAfterEnd && x.EndTime < DateTime.Now)
+ .ExecuteCommandAsync();
+ LogHelper.Info($"{cnt2}条订单的拉取状态由SilenceAfterEnd更新为Completed");
+
+ return cnt1 + cnt2;
+ }
+
private int UpdateOrderQuestionType(int questionType, IEnumerable ids)
{
var idsString = string.Join(",", ids);
diff --git a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs
index 8d41c9c2..5b16582d 100644
--- a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs
+++ b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs
@@ -152,7 +152,6 @@ internal class DetailsEsRepository : ElasticSearchContextAbstract tracks)
{
- if (!tracks.Any()) return;
// 按天写入es
var indexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}";
tracks.ForEach(x => x.IndexName = indexName);