From d517df75dea52b6a921e563aa14d8f7aef57aac3 Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Wed, 26 Aug 2020 11:02:48 +0800 Subject: [PATCH] change notification data --- aspnet-core/LINGYUN.MicroService.sln | 11 +++- .../AbpNotificationsExceptionSubscriber.cs | 10 +++- .../SignalR/OnlineClientHubBase.cs | 6 +- .../SignalRNotificationPublishProvider.cs | 57 ++++++++++++------- .../Abp/Notifications/NotificationData.cs | 50 ++++++++++++++++ .../Notifications/NotificationDefinition.cs | 5 ++ .../Abp/Notifications/NotificationType.cs | 10 +++- .../UserCreateSendWelcomeEventHandler.cs | 2 +- .../Distributed/NotificationEventHandler.cs | 15 ++++- .../Distributed/TenantCreateEventHandler.cs | 2 +- 10 files changed, 138 insertions(+), 30 deletions(-) diff --git a/aspnet-core/LINGYUN.MicroService.sln b/aspnet-core/LINGYUN.MicroService.sln index af232f52f..9cbfa579d 100644 --- a/aspnet-core/LINGYUN.MicroService.sln +++ b/aspnet-core/LINGYUN.MicroService.sln @@ -209,9 +209,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.EntityFrameworkCore", "modules\identityServer\LINGYUN.Abp.IdentityServer.EntityFrameworkCore\LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj", "{5D0ED1FC-3A7C-4531-9512-832E73AD9555}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{2BF7FB73-0C62-4ECF-99F0-0583855D2777}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{2BF7FB73-0C62-4ECF-99F0-0583855D2777}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.EntityFrameworkCore", "modules\identity\LINGYUN.Abp.Identity.EntityFrameworkCore\LINGYUN.Abp.Identity.EntityFrameworkCore.csproj", "{6FE7E243-2D99-4567-8786-6C9283D608EF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.EntityFrameworkCore", "modules\identity\LINGYUN.Abp.Identity.EntityFrameworkCore\LINGYUN.Abp.Identity.EntityFrameworkCore.csproj", "{6FE7E243-2D99-4567-8786-6C9283D608EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.AspNetCore.Mvc", "modules\common\LINGYUN.Abp.Notifications.AspNetCore.Mvc\LINGYUN.Abp.Notifications.AspNetCore.Mvc.csproj", "{1A9C06D0-1A12-48C6-B3F6-F2DBC66AA355}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -567,6 +569,10 @@ Global {6FE7E243-2D99-4567-8786-6C9283D608EF}.Debug|Any CPU.Build.0 = Debug|Any CPU {6FE7E243-2D99-4567-8786-6C9283D608EF}.Release|Any CPU.ActiveCfg = Release|Any CPU {6FE7E243-2D99-4567-8786-6C9283D608EF}.Release|Any CPU.Build.0 = Release|Any CPU + {1A9C06D0-1A12-48C6-B3F6-F2DBC66AA355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A9C06D0-1A12-48C6-B3F6-F2DBC66AA355}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A9C06D0-1A12-48C6-B3F6-F2DBC66AA355}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A9C06D0-1A12-48C6-B3F6-F2DBC66AA355}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -674,6 +680,7 @@ Global {5D0ED1FC-3A7C-4531-9512-832E73AD9555} = {0439B173-F41E-4CE0-A44A-CCB70328F272} {2BF7FB73-0C62-4ECF-99F0-0583855D2777} = {52B5D4F7-237B-4E0A-A167-68442164F70A} {6FE7E243-2D99-4567-8786-6C9283D608EF} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {1A9C06D0-1A12-48C6-B3F6-F2DBC66AA355} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN/Abp/ExceptionHandling/Notifications/AbpNotificationsExceptionSubscriber.cs b/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN/Abp/ExceptionHandling/Notifications/AbpNotificationsExceptionSubscriber.cs index 3dd7f4fda..26c2a5c2a 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN/Abp/ExceptionHandling/Notifications/AbpNotificationsExceptionSubscriber.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN/Abp/ExceptionHandling/Notifications/AbpNotificationsExceptionSubscriber.cs @@ -24,7 +24,15 @@ namespace LINGYUN.Abp.ExceptionHandling.Notifications var notificationDispatcher = context.ServiceProvider.GetRequiredService(); var notificationName = NotificationNameNormalizer .NormalizerName(AbpExceptionHandlingNotificationNames.NotificationName); - var notificationData = new NotificationData(); + NotificationData notificationData; + if (CurrentTenant.IsAvailable) + { + notificationData = NotificationData.CreateTenantNotificationData(CurrentTenant.Id.Value); + } + else + { + notificationData = NotificationData.CreateNotificationData(); + } // 写入通知数据 //TODO:集成TextTemplate完成格式化的推送 notificationData.WriteStandardData( diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs index 04c341cb6..f091ecf06 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs @@ -1,6 +1,5 @@ using LINGYUN.Abp.RealTime.Client; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using System; using System.Threading.Tasks; @@ -26,6 +25,11 @@ namespace LINGYUN.Abp.Notifications.SignalR IOnlineClient onlineClient = CreateClientForCurrentConnection(); Logger.LogDebug("A client is connected: " + onlineClient.ToString()); OnlineClientManager.Add(onlineClient); + if (onlineClient.TenantId.HasValue) + { + // 以租户为分组,将用户加入租户通讯组 + await Groups.AddToGroupAsync(onlineClient.ConnectionId, onlineClient.TenantId.Value.ToString()); + } } public override async Task OnDisconnectedAsync(Exception exception) diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs index 04afc41a8..0bfa29e70 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs @@ -30,31 +30,48 @@ namespace LINGYUN.Abp.Notifications.SignalR public override async Task PublishAsync(NotificationInfo notification, IEnumerable identifiers) { - // 返回标准数据给前端 - notification.Data = NotificationData.ToStandardData(notification.Data); - foreach (var identifier in identifiers) + if (notification.Data.HasTenantNotification(out Guid tenantId)) { - Logger.LogDebug($"Find online client with user {identifier.UserId} - {identifier.UserName}"); - var onlineClientContext = new OnlineClientContext(notification.TenantId, identifier.UserId); - var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext); - foreach (var onlineClient in onlineClients) + // 返回标准数据给前端 + notification.Data = NotificationData.ToStandardData(notification.Data); + var singalRGroup = _hubContext.Clients.Group(tenantId.ToString()); + if (singalRGroup == null) { - try + Logger.LogDebug("Can not get group " + tenantId + " from SignalR hub!"); + return; + } + // 租户通知群发 + Logger.LogDebug($"Found a singalr group, begin senging notifications"); + await singalRGroup.SendAsync("getNotification", notification); + } + else + { + // 返回标准数据给前端 + notification.Data = NotificationData.ToStandardData(notification.Data); + foreach (var identifier in identifiers) + { + Logger.LogDebug($"Find online client with user {identifier.UserId} - {identifier.UserName}"); + var onlineClientContext = new OnlineClientContext(notification.TenantId, identifier.UserId); + var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext); + foreach (var onlineClient in onlineClients) { - Logger.LogDebug($"Find online client {onlineClient.UserId} - {onlineClient.ConnectionId}"); - var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId); - if (signalRClient == null) + try { - Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!"); - continue; + Logger.LogDebug($"Find online client {onlineClient.UserId} - {onlineClient.ConnectionId}"); + var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId); + if (signalRClient == null) + { + Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!"); + continue; + } + Logger.LogDebug($"Found a singalr client, begin senging notifications"); + await signalRClient.SendAsync("getNotification", notification); + } + catch (Exception ex) + { + Logger.LogWarning("Could not send notifications to user: {0}", identifier.UserId); + Logger.LogWarning("Send to user notifications error: {0}", ex.Message); } - Logger.LogDebug($"Found a singalr client, begin senging notifications"); - await signalRClient.SendAsync("getNotification", notification); - } - catch (Exception ex) - { - Logger.LogWarning("Could not send notifications to user: {0}", identifier.UserId); - Logger.LogWarning("Send to user notifications error: {0}", ex.Message); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationData.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationData.cs index ea6e40578..c9955adba 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationData.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationData.cs @@ -5,6 +5,10 @@ namespace LINGYUN.Abp.Notifications { public class NotificationData { + public const string NotificationKey = "N:G"; + public const string UserIdNotificationKey = "N:UI"; + public const string UserNameNotificationKey = "N:UN"; + public const string TenantNotificationKey = "N:T"; public virtual string Type => GetType().FullName; public object this[string key] @@ -45,6 +49,29 @@ namespace LINGYUN.Abp.Notifications { _properties = new Dictionary(); } + + public static NotificationData CreateNotificationData() + { + var data = new NotificationData(); + data.TrySetData(NotificationKey, "AbpNotification"); + return data; + } + + public static NotificationData CreateUserNotificationData(Guid userId, string userName) + { + var data = new NotificationData(); + data.TrySetData(UserIdNotificationKey, userId); + data.TrySetData(UserNameNotificationKey, userName); + return data; + } + + public static NotificationData CreateTenantNotificationData(Guid tenantId) + { + var data = new NotificationData(); + data.TrySetData(TenantNotificationKey, tenantId); + return data; + } + /// /// 写入标准数据 /// @@ -123,5 +150,28 @@ namespace LINGYUN.Abp.Notifications Properties[key] = value; } } + + public bool HasUserNotification(out Guid userId, out string userName) + { + if (Properties.TryGetValue(UserIdNotificationKey, out object userKey)) + { + userId = (Guid)userKey; + var name = TryGetData(UserNameNotificationKey); + userName = name != null ? name.ToString() : ""; + return true; + } + userName = ""; + return false; + } + + public bool HasTenantNotification(out Guid tenantId) + { + if (Properties.TryGetValue(TenantNotificationKey, out object tenantKey)) + { + tenantId = (Guid)tenantKey; + return true; + } + return false; + } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs index f585fbafb..3a0c8f3c5 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs @@ -9,6 +9,11 @@ using Volo.Abp.Localization; * 而是规范通知的一些属性,因此不应该是自定义通知名称,而是定义通知的类目,类似于Catalog * 或者Prefix * + * TODO: 2020-08-26 如果需要用户或者租户特定的消息该如何来发送通知? + * 是否追加字段:通知类别(宿主、租户、用户、通用),主要可以在运行时判断发布消息的来源, + * 如果是用户通知(NotificationData[FormUser])则只会查询用户对于用户通知的订阅(用户互动:站内信、私信、好友请求、留言等),优先级最低 + * 租户通知(NotificationData[FormTenant])则只会查询用户对于租户通知的订阅(系统发布、应用通知),优先级次于用户 + * 全局通知(NotificationData[FormGlobal])则查询用户对于全局通知的订阅(一般用于系统发布、应用通知),优先级最高 */ namespace LINGYUN.Abp.Notifications diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationType.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationType.cs index ce5db6c6c..f13b34542 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationType.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationType.cs @@ -6,12 +6,16 @@ public enum NotificationType { /// - /// 应用 + /// 应用(对应租户) /// Application = 0, /// - /// 系统 + /// 系统(对应宿主) /// - System = 10 + System = 10, + /// + /// 用户(对应用户) + /// + User = 20 } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs index 672f1cb08..d2b53d23a 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs @@ -61,7 +61,7 @@ namespace LINGYUN.Abp.MessageService.EventBus //await _notificationStore.InsertUserSubscriptionAsync(eventData.Entity.TenantId, // userIdentifer, UserNotificationNames.WelcomeToApplication); - var userWelcomeNotifictionData = new NotificationData(); + var userWelcomeNotifictionData = NotificationData.CreateUserNotificationData(eventData.Entity.Id, eventData.Entity.UserName); userWelcomeNotifictionData.WriteStandardData( L("WelcomeToApplicationFormUser", eventData.Entity.Name ?? eventData.Entity.UserName), diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs index a3ffed6e2..ec9408620 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs @@ -39,6 +39,10 @@ namespace LINGYUN.Abp.MessageService.EventBus.Distributed /// protected INotificationStore NotificationStore { get; } /// + /// Reference to . + /// + protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } + /// /// Reference to . /// protected INotificationPublishProviderManager NotificationPublishProviderManager { get; } @@ -50,11 +54,13 @@ namespace LINGYUN.Abp.MessageService.EventBus.Distributed IBackgroundJobManager backgroundJobManager, IOptions options, INotificationStore notificationStore, + INotificationSubscriptionManager notificationSubscriptionManager, INotificationPublishProviderManager notificationPublishProviderManager) { BackgroundJobManager = backgroundJobManager; Options = options.Value; NotificationStore = notificationStore; + NotificationSubscriptionManager = notificationSubscriptionManager; NotificationPublishProviderManager = notificationPublishProviderManager; Logger = NullLogger.Instance; @@ -85,9 +91,16 @@ namespace LINGYUN.Abp.MessageService.EventBus.Distributed // 持久化通知 await NotificationStore.InsertNotificationAsync(notificationInfo); + // TODO: 某些情况下,不能直接在服务内订阅消息,目前只能通过将订阅内容放进消息内部,需要重构通知系统设计了 + if (notificationInfo.Data.HasUserNotification(out Guid userId, out string userName)) + { + await NotificationSubscriptionManager.SubscribeAsync(notificationInfo.TenantId, + new UserIdentifier(userId, userName), notificationInfo.Name); + } + Logger.LogDebug($"Gets a list of user subscriptions {notificationInfo.Name}"); // 获取用户订阅列表 - var userSubscriptions = await NotificationStore.GetSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name); + var userSubscriptions = await NotificationSubscriptionManager.GetSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name); Logger.LogDebug($"Persistent user notifications {notificationInfo.Name}"); // 持久化用户通知 diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/TenantCreateEventHandler.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/TenantCreateEventHandler.cs index 9053a16e9..f7aeb94ec 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/TenantCreateEventHandler.cs +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/TenantCreateEventHandler.cs @@ -55,7 +55,7 @@ namespace LINGYUN.Abp.MessageService.EventBus.Distributed // 管理用户订阅租户创建通知 await NotificationSubscriptionManager.SubscribeAsync(eventData.Id, tenantAdminUserIdentifier, noticeNormalizerName.Name); - var notificationData = new NotificationData(); + var notificationData = NotificationData.CreateTenantNotificationData(eventData.Id); notificationData.WriteStandardData( L("NewTenantRegisteredNotificationTitle"), L("NewTenantRegisteredNotificationMessage", eventData.Name),