梳理预警通知

This commit is contained in:
xiaolipro 2024-09-18 10:38:32 +08:00
parent 6ed311bc1f
commit f42e2db302
18 changed files with 103 additions and 103 deletions

View File

@ -1,4 +1,4 @@
namespace SJZY.Track.Domain.Dtos.Forewarning; namespace SJZY.Track.Application.Contract.Dtos.Forewarning;
public class AreaCacheEntry public class AreaCacheEntry
{ {

View File

@ -1,4 +1,4 @@
namespace SJZY.Track.Domain.Dtos.Forewarning; namespace SJZY.Track.Application.Contract.Dtos.Forewarning;
public class ForewarningRuleCacheEntry public class ForewarningRuleCacheEntry
{ {

View File

@ -1,4 +1,4 @@
namespace SJZY.Track.Domain.Dtos.Forewarning; namespace SJZY.Track.Application.Contract.Dtos.Forewarning;
public class RuleAreaBaseInfo public class RuleAreaBaseInfo
{ {

View File

@ -0,0 +1,8 @@
using SJZY.Track.Application.Contract.Dtos.Forewarning;
namespace SJZY.Track.Application.Contract.Events;
public class ClearRulCacheEvent
{
public List<RuleAreaBaseInfo> Items { get; set; }
}

View File

@ -1,6 +1,7 @@
using SJZY.Track.Domain.Dtos.Forewarning; using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Application.Contract.Events;
namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; namespace SJZY.Track.Application.Contract.Services;
public interface IForewarningCacheService public interface IForewarningCacheService
{ {

View File

@ -23,10 +23,11 @@ public class TrackButtonUpScanner : BackgroundService
_orderRepository = orderRepository; _orderRepository = orderRepository;
} }
protected override Task ExecuteAsync(CancellationToken stoppingToken) protected override Task ExecuteAsync(CancellationToken stoppingToken)
{ {
throw new NotImplementedException(); // 查看哪些要兜底的轨迹(服务商拉取的,且时区发生地是空的),根据子系统、服务商分组尝试兜底
// 维护轨迹明细、订单主表
return Task.CompletedTask;
} }
/// <summary> /// <summary>

View File

@ -1,7 +1,7 @@
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using SJZY.Expand.ABP.Core; using SJZY.Expand.ABP.Core;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Domain.Dtos.Forewarning; using SJZY.Track.Application.Contract.Services;
namespace SJZY.Track.Application.HostServices; namespace SJZY.Track.Application.HostServices;

View File

@ -9,11 +9,10 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BSI.Stack.Rabbit" Version="2.0.9" /> <PackageReference Include="BSI.Stack.Rabbit" Version="2.0.9" />
<PackageReference Include="SJZY.FSCenter.Client" Version="1.5.7"/>
<PackageReference Include="SJZY.InterfaceRelay.Application.Contracts" Version="7.2.3"/> <PackageReference Include="SJZY.InterfaceRelay.Application.Contracts" Version="7.2.3"/>
<PackageReference Include="Volo.Abp.Http.Client" Version="7.0.2" /> <PackageReference Include="Volo.Abp.Http.Client" Version="7.0.2" />
<PackageReference Include="Volo.Abp.FluentValidation" Version="7.0.2" /> <PackageReference Include="Volo.Abp.FluentValidation" Version="7.0.2" />
<PackageReference Include="SJZY.UserCenter.HttpApi" Version="3.0.9-alpha"/> <PackageReference Include="SJZY.UserCenter.HttpApi" Version="3.0.9-alpha9"/>
<PackageReference Include="SJZY.Expand.CAP" Version="7.8.0" /> <PackageReference Include="SJZY.Expand.CAP" Version="7.8.0" />
<PackageReference Include="DotNetCore.CAP" Version="8.2.0"/> <PackageReference Include="DotNetCore.CAP" Version="8.2.0"/>
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="8.2.0"/> <PackageReference Include="DotNetCore.CAP.Dashboard" Version="8.2.0"/>

View File

@ -1,7 +1,9 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using SJZY.Expand.ABP.Core; using SJZY.Expand.ABP.Core;
using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; using SJZY.Track.Domain.Aggregates.KPIAreaAggregate;
using SJZY.Track.Domain.Dtos.Forewarning; using SJZY.Track.Domain.Dtos.Forewarning;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
@ -64,7 +66,7 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
public async Task ClearRedisByAreaId(int areaId) public async Task ClearRedisByAreaId(int areaId)
{ {
var baseInfos = await _warningQueries.GetWarningRuleByAreaId(areaId); var baseInfos = await _warningQueries.GetWarningRuleByAreaId(areaId);
if (baseInfos == null || baseInfos.Count == 0) return; if (!baseInfos.Any()) return;
baseInfos = baseInfos.DistinctBy(val => WarningKey(val.SystemId, val.CustomerId)).ToList(); baseInfos = baseInfos.DistinctBy(val => WarningKey(val.SystemId, val.CustomerId)).ToList();
var willDelKeys = baseInfos.Select(val => WarningKey(val.SystemId, val.CustomerId)).ToArray(); var willDelKeys = baseInfos.Select(val => WarningKey(val.SystemId, val.CustomerId)).ToArray();
@ -72,7 +74,11 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
await RedisHelper.Client.DelAsync(AreaKey(areaId)); await RedisHelper.Client.DelAsync(AreaKey(areaId));
var eventModel = new ClearRulCacheEvent var eventModel = new ClearRulCacheEvent
{ {
Items = baseInfos Items = baseInfos.Select(x => new RuleAreaBaseInfo
{
SystemId = x.SystemId,
CustomerId = x.CustomerId
}).ToList()
}; };
await PublishEvent(eventModel); await PublishEvent(eventModel);

View File

@ -2,9 +2,6 @@ using System.Text;
using FreeRedis; using FreeRedis;
using SJZY.Expand.ABP.Core; using SJZY.Expand.ABP.Core;
using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.Logger;
using SJZY.FSCenter.Application.Dtos.Message;
using SJZY.FSCenter.Client.Client.Message;
using SJZY.FSCenter.Repository.Enum;
using SJZY.Track.Application.Contract.Dtos.Forewarning; using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Application.Contract.Services; using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
@ -24,23 +21,23 @@ namespace SJZY.Track.Application.Services.ForewarningServices;
/// </summary> /// </summary>
public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency
{ {
private readonly IForewarningCacheService _cacheService; private readonly IForewarningCacheService _forewarningCacheService;
private readonly IMessageClient _messageClient;
private readonly IHttpClientProxy<IRequestSendMessageService> _requestSendMessageService; private readonly IHttpClientProxy<IRequestSendMessageService> _requestSendMessageService;
private readonly IWarningQueries _warningQueries; private readonly IWarningQueries _warningQueries;
private readonly IWarningRecordEsRepository _warningRecordEsRepository; private readonly IWarningRecordEsRepository _warningRecordEsRepository;
public ForewarningNotifyService(IForewarningCacheService cacheService, IWarningQueries warningQueries, public ForewarningNotifyService(IWarningQueries warningQueries,
IWarningRecordEsRepository warningRecordEsRepository, IWarningRecordEsRepository warningRecordEsRepository,
IHttpClientProxy<IRequestSendMessageService> requestSendMessageService, IMessageClient messageClient) IHttpClientProxy<IRequestSendMessageService> requestSendMessageService,
IForewarningCacheService forewarningCacheService)
{ {
_cacheService = cacheService;
_warningQueries = warningQueries; _warningQueries = warningQueries;
_warningRecordEsRepository = warningRecordEsRepository; _warningRecordEsRepository = warningRecordEsRepository;
_requestSendMessageService = requestSendMessageService; _requestSendMessageService = requestSendMessageService;
_messageClient = messageClient; _forewarningCacheService = forewarningCacheService;
} }
/// <summary> /// <summary>
/// 创建预警通知 /// 创建预警通知
/// </summary> /// </summary>
@ -49,7 +46,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
{ {
if (dto.Orders.Count == 0) return; if (dto.Orders.Count == 0) return;
var rules = await _cacheService.GetRulesAsync(dto.SubSystemId, dto.CustomerId); var rules = await _forewarningCacheService.GetRulesAsync(dto.SubSystemId, dto.CustomerId);
if (rules == null || rules.Count == 0) return; if (rules == null || rules.Count == 0) return;
var adds = new List<(int ruleId, int orderId, int counter, long ts)>(); var adds = new List<(int ruleId, int orderId, int counter, long ts)>();
@ -134,7 +131,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
var warningRecords = await WriteWarningRecordAsync(entries, notifyRules); var warningRecords = await WriteWarningRecordAsync(entries, notifyRules);
// 发通知 // 发通知
await SendCoreAsync(entries, notifyRules); await SendCoreAsync(subSystemId, entries, notifyRules);
// 移除已处理的预警 // 移除已处理的预警
await RedisHelper.Client.ZRemRangeByScoreAsync(redisKey, 0, timestamp); await RedisHelper.Client.ZRemRangeByScoreAsync(redisKey, 0, timestamp);
@ -169,7 +166,8 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
return warningRecords; return warningRecords;
} }
private Task SendCoreAsync(List<WarningNotifyCacheEntry> entries, List<GetWarningNotifiesVo> notifyRules) private Task SendCoreAsync(int subSystemId, List<WarningNotifyCacheEntry> entries,
List<GetWarningNotifiesVo> notifyRules)
{ {
var userRules = new Dictionary<int, List<GetWarningNotifiesVo>>(); var userRules = new Dictionary<int, List<GetWarningNotifiesVo>>();
foreach (var rule in notifyRules) foreach (var rule in notifyRules)
@ -187,64 +185,10 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
foreach (var userRule in userRules) foreach (var userRule in userRules)
{ {
var siteInternalContent = BuildNotifyContent(userRule.Value, entries, NotifyMode.SiteInternal); // 以人的维度发送通知,异步
var feiShuContent = BuildNotifyContent(userRule.Value, entries, NotifyMode.FeiShu); _ = DoNotifyAsync(subSystemId, userRule.Key, userRule.Value, entries,
NotifyMode.SiteInternal);
if (!string.IsNullOrEmpty(siteInternalContent)) _ = DoNotifyAsync(subSystemId, userRule.Key, userRule.Value, entries, NotifyMode.FeiShu);
{
_ = Task.Run(async () =>
{
// todo:发送站内通知
var res = await _requestSendMessageService.Service.SendMessageByEmptyTemplateAsync(
new SendMessageByEmptyTemplateInput
{
IsNeedToHandle = null,
BizId = null,
MsgSource = null,
SystemId = 0,
TemplateCode = null,
Channels = null,
MsgTitle = null,
MsgContent = null,
PcURl = null,
MobileURl = null,
FileUrl = null,
fileName = null,
receivers = null,
SiteLetterComponentStyle = (ComponentStyle) 0
});
if (res.Code != GlobalConst.SuccessCode)
{
LogHelper.Error($"发送站内通知失败,用户:{userRule.Key},内容:{siteInternalContent}");
}
});
}
if (!string.IsNullOrEmpty(feiShuContent))
{
_ = Task.Run(async () =>
{
// 发送飞书通知
var res = await _messageClient.SendMessageAsync(new SendMessageInput
{
AppId = null,
AppSecret = null,
ReceiveIdType = IdTypeEnums.user_id,
MsgType = MsgTypeEnums.文本,
ReceiveIds = new List<string>
{
userRule.Key.ToString()
},
Content = feiShuContent
});
if (res.Code != GlobalConst.SuccessCode)
{
LogHelper.Error($"发送飞书通知失败,用户:{userRule.Key},内容:{feiShuContent}");
}
});
}
} }
return Task.CompletedTask; return Task.CompletedTask;
@ -253,7 +197,8 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
private string GetForewarningNotifySetKeyRedisKey(int subSystemId) => private string GetForewarningNotifySetKeyRedisKey(int subSystemId) =>
$"{GlobalConst.ForewarningNotifySetKey}:{subSystemId}"; $"{GlobalConst.ForewarningNotifySetKey}:{subSystemId}";
private string BuildNotifyContent(List<GetWarningNotifiesVo> rules, List<WarningNotifyCacheEntry> entries, private async Task DoNotifyAsync(int subSystemId, int userId, List<GetWarningNotifiesVo> rules,
List<WarningNotifyCacheEntry> entries,
NotifyMode mode) NotifyMode mode)
{ {
/* 以人的维度发送通知 /* 以人的维度发送通知
@ -283,7 +228,37 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
} }
} }
return notifyContent.ToString(); var msgContent = notifyContent.ToString();
if (string.IsNullOrEmpty(msgContent)) return;
var res = await _requestSendMessageService.Service.SendMessageByEmptyTemplateAsync(
new SendMessageByEmptyTemplateInput
{
IsNeedToHandle = true,
MsgSource = MsgSourceEnum.系统提醒,
SystemId = subSystemId,
TemplateCode = "trackWarning",
Channels = new List<ChannelEnum>()
{
mode == NotifyMode.FeiShu ? ChannelEnum.飞书 : ChannelEnum.站内信,
},
MsgTitle = "轨迹运输时效预警",
MsgContent = msgContent,
receivers = new List<MsgInstanceReceiverInput>
{
new()
{
RecipientType = 1,
ReceiverId = userId,
}
},
});
if (res.Code != GlobalConst.SuccessCode)
{
LogHelper.Error($"发送{mode.ToString()}通知失败,用户:{userId},内容:{msgContent}");
}
} }
private static List<ForewarningRuleCacheEntry> MatchRule(List<ForewarningRuleCacheEntry> rules, private static List<ForewarningRuleCacheEntry> MatchRule(List<ForewarningRuleCacheEntry> rules,

View File

@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using SJZY.Track.Application.Contract.Dtos.Forewarning; using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Application.Helpers; using SJZY.Track.Application.Helpers;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate; using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
@ -22,7 +23,6 @@ public class ForewarningService : ApplicationService
_forewarningCacheService = forewarningCacheService; _forewarningCacheService = forewarningCacheService;
} }
/// <summary> /// <summary>
/// 获取预警分页列表 /// 获取预警分页列表
/// </summary> /// </summary>

View File

@ -1,4 +1,4 @@
using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; using SJZY.Track.Domain.Aggregates.KPIAreaAggregate;
using SJZY.Track.Domain.Dtos.Forewarning; using SJZY.Track.Domain.Dtos.Forewarning;

View File

@ -7,8 +7,8 @@ using Savorboard.CAP.InMemoryMessageQueue;
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.Expand.ABP.Core.PublicMethords;
using SJZY.FSCenter.Client;
using SJZY.InterfaceRelay.Application.Contracts; using SJZY.InterfaceRelay.Application.Contracts;
using SJZY.Track.Application.BackgroundServices;
using SJZY.Track.Application.CAP; using SJZY.Track.Application.CAP;
using SJZY.Track.Application.Contract; using SJZY.Track.Application.Contract;
using SJZY.Track.Application.Localization; using SJZY.Track.Application.Localization;
@ -35,8 +35,7 @@ namespace SJZY.Track.Application;
typeof(SjzyUserCenterHttpApiModule), typeof(SjzyUserCenterHttpApiModule),
typeof(SJZYInterfaceRelayApplicationContractsModule), typeof(SJZYInterfaceRelayApplicationContractsModule),
typeof(SjzyTrackDomainModule), typeof(SjzyTrackDomainModule),
typeof(SjzyTrackApplicationContractModule), typeof(SjzyTrackApplicationContractModule)
typeof(FSCenterModule)
)] )]
public class SjzyTrackApplicationModule : AbpModule public class SjzyTrackApplicationModule : AbpModule
{ {
@ -152,8 +151,8 @@ public class SjzyTrackApplicationModule : AbpModule
}; };
}, typeof(SjzyTrackApplicationModule).Assembly); }, typeof(SjzyTrackApplicationModule).Assembly);
// 飞书 context.Services.AddHostedService<OrderPullStatusScanner>();
context.Services.Configure<SystemKeyOption>(option => { option.SystemKey = "aaa"; }); context.Services.AddHostedService<TrackButtonUpScanner>();
} }
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)

View File

@ -1,6 +0,0 @@
namespace SJZY.Track.Domain.Dtos.Forewarning;
public class ClearRulCacheEvent
{
public List<RuleAreaBaseInfo> Items { get; set; }
}

View File

@ -0,0 +1,17 @@
namespace SJZY.Track.Domain.Dtos.Forewarning;
public class RuleAreaBaseInfoVo
{
public RuleAreaBaseInfoVo()
{
}
public RuleAreaBaseInfoVo(int systemId, int customerId)
{
SystemId = systemId;
CustomerId = customerId;
}
public int SystemId { get; set; }
public int CustomerId { get; set; }
}

View File

@ -23,5 +23,5 @@ public interface IWarningQueries
/// </summary> /// </summary>
/// <param name="areaId"></param> /// <param name="areaId"></param>
/// <returns></returns> /// <returns></returns>
Task<List<RuleAreaBaseInfo>?> GetWarningRuleByAreaId(int areaId); Task<List<RuleAreaBaseInfoVo>> GetWarningRuleByAreaId(int areaId);
} }

View File

@ -79,12 +79,12 @@ public class WarningQueries : ISugarRepository, IWarningQueries,
.ToListAsync(); .ToListAsync();
} }
public Task<List<RuleAreaBaseInfo>?> GetWarningRuleByAreaId(int areaId) public Task<List<RuleAreaBaseInfoVo>> GetWarningRuleByAreaId(int areaId)
{ {
return Context.Queryable<WarningRuleEntity>() return Context.Queryable<WarningRuleEntity>()
.InnerJoin<WarningEntity>((a, b) => a.WarningId == b.Id) .InnerJoin<WarningEntity>((a, b) => a.WarningId == b.Id)
.Where((a, b) => b.IsEnable && a.AreaId == areaId) .Where((a, b) => b.IsEnable && a.AreaId == areaId)
.Select((a, b) => new RuleAreaBaseInfo .Select((a, b) => new RuleAreaBaseInfoVo
{ {
CustomerId = b.CustomerId, CustomerId = b.CustomerId,
SystemId = b.SubSystemId SystemId = b.SubSystemId

View File

@ -10,7 +10,7 @@
<PackageReference Include="SJZY.LoggerCenter.HttpApi" Version="7.0.5" /> <PackageReference Include="SJZY.LoggerCenter.HttpApi" Version="7.0.5" />
<PackageReference Include="SJZY.OTel.Extension" Version="1.0.4"/> <PackageReference Include="SJZY.OTel.Extension" Version="1.0.4"/>
<PackageReference Include="Volo.Abp.Autofac" Version="7.0.2" /> <PackageReference Include="Volo.Abp.Autofac" Version="7.0.2" />
<PackageReference Include="SJZY.UserCenter.HttpApi" Version="3.0.9-alpha"/> <PackageReference Include="SJZY.UserCenter.HttpApi" Version="3.0.9-alpha9"/>
<PackageReference Include="SJZY.Expand.CAP" Version="7.8.0" /> <PackageReference Include="SJZY.Expand.CAP" Version="7.8.0" />
</ItemGroup> </ItemGroup>