Browse Source

增强通知功能,增加通知生命周期

pull/7/head
cKey 6 years ago
parent
commit
5366b2909d
  1. 6
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs
  2. 18
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationSender.cs
  3. 8
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDispatcher.cs
  4. 37
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs
  5. 6
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs
  6. 2
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationEventData.cs
  7. 3
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs
  8. 18
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationLifetime.cs
  9. 4
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpMessageServiceNotificationDefinitionProvider.cs
  10. 5
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs
  11. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/IUserSubscribeRepository.cs
  12. 6
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs
  13. 7
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs
  14. 7
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Notifications/MessageServiceDefinitionProvider.cs

6
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Notifications.SignalR
@ -31,22 +32,23 @@ namespace LINGYUN.Abp.Notifications.SignalR
{
// 返回标准数据给前端
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)
{
try
{
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)

18
aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationSender.cs

@ -1,4 +1,6 @@
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Net.Http;
@ -13,6 +15,7 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
public class WeChatWeAppNotificationSender : IWeChatWeAppNotificationSender, ITransientDependency
{
public const string SendNotificationClientName = "WeChatWeAppSendNotificationClient";
public ILogger<WeChatWeAppNotificationSender> Logger { get; set; }
protected IHttpClientFactory HttpClientFactory { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IWeChatTokenProvider WeChatTokenProvider { get; }
@ -24,6 +27,8 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
JsonSerializer = jsonSerializer;
HttpClientFactory = httpClientFactory;
WeChatTokenProvider = weChatTokenProvider;
Logger = NullLogger<WeChatWeAppNotificationSender>.Instance;
}
public virtual async Task SendAsync(WeChatWeAppSendNotificationData notificationData)
@ -38,7 +43,14 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
var requestUrl = BuildRequestUrl(weChatSendNotificationUrl, weChatSendNotificationPath, requestParamters);
var responseContent = await MakeRequestAndGetResultAsync(requestUrl, notificationData);
var weChatSenNotificationResponse = JsonSerializer.Deserialize<WeChatSendNotificationResponse>(responseContent);
weChatSenNotificationResponse.ThrowIfNotSuccess();
if (!weChatSenNotificationResponse.IsSuccessed)
{
Logger.LogWarning("Send wechat we app subscribe message failed");
Logger.LogWarning($"Error code: {weChatSenNotificationResponse.ErrorCode}, message: {weChatSenNotificationResponse.ErrorMessage}");
}
// 失败是否抛出异常
// weChatSenNotificationResponse.ThrowIfNotSuccess();
}
protected virtual async Task<string> MakeRequestAndGetResultAsync(string url, WeChatWeAppSendNotificationData notificationData)
{
@ -53,7 +65,7 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
var response = await client.SendAsync(requestMessage);
if (!response.IsSuccessStatusCode)
{
throw new AbpException($"Baidu http request service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}");
throw new AbpException($"WeChat send subscribe message http request service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}");
}
var resultContent = await response.Content.ReadAsStringAsync();
@ -83,6 +95,8 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
[JsonProperty("errmsg")]
public string ErrorMessage { get; set; }
public bool IsSuccessed => ErrorCode == 0;
public void ThrowIfNotSuccess()
{
if (ErrorCode != 0)

8
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDispatcher.cs

@ -8,14 +8,6 @@ namespace LINGYUN.Abp.Notifications
/// </summary>
public interface INotificationDispatcher
{
/// <summary>
/// 发送通知
/// </summary>
/// <param name="notification"></param>
/// <returns></returns>
[Obsolete("Api已过时,请调用 DispatcheAsync(string notificationName, NotificationData data, Guid? tenantId = null)")]
Task DispatchAsync(NotificationInfo notification);
/// <summary>
/// 发送通知
/// </summary>

37
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs

@ -84,6 +84,7 @@ namespace LINGYUN.Abp.Notifications.Internal
Name = notificationName.Name,
CreationTime = DateTime.Now,
NotificationSeverity = notificationSeverity,
Lifetime = defineNotification.NotificationLifetime,
NotificationType = defineNotification.NotificationType,
TenantId = tenantId,
Data = data
@ -98,6 +99,13 @@ namespace LINGYUN.Abp.Notifications.Internal
}
await PublishFromProvidersAsync(providers, notificationInfo);
if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne)
{
// 一次性通知在发送完成后就取消用户订阅
await _notificationStore.DeleteAllUserSubscriptionAsync(notificationInfo.TenantId,
notificationInfo.Name);
}
}
/// <summary>
/// 发送通知事件
@ -119,6 +127,7 @@ namespace LINGYUN.Abp.Notifications.Internal
Name = notificationName.Name,
CreationTime = DateTime.Now,
NotificationSeverity = notificationSeverity,
Lifetime = defineNotification.NotificationLifetime,
NotificationType = defineNotification.NotificationType,
TenantId = tenantId,
Data = data
@ -126,34 +135,6 @@ namespace LINGYUN.Abp.Notifications.Internal
// 发布分布式通知事件,让消息中心统一处理
await DistributedEventBus.PublishAsync(notificationEventData);
}
/// <summary>
/// 发送通知
/// </summary>
/// <param name="notification">通知信息</param>
/// <returns></returns>
public virtual async Task DispatchAsync(NotificationInfo notification)
{
// 获取自定义的通知
var defineNotification = _notificationDefinitionManager.GetOrNull(notification.Name);
// 没有定义的通知,应该也要能发布、订阅,
// 比如订单之类的,是以订单编号为通知名称,这是动态的,没法自定义
if (defineNotification == null)
{
defineNotification = new NotificationDefinition(notification.Name);
}
var providers = Enumerable
.Reverse(_notificationPublishProviderManager.Providers);
if (defineNotification.Providers.Any())
{
providers = providers.Where(p => defineNotification.Providers.Contains(p.Name));
}
await PublishFromProvidersAsync(providers, notification);
}
/// <summary>
/// 指定提供者发布通知
/// </summary>

6
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs

@ -40,6 +40,10 @@ namespace LINGYUN.Abp.Notifications
/// </summary>
public bool AllowSubscriptionToClients { get; set; }
/// <summary>
/// 存活类型
/// </summary>
public NotificationLifetime NotificationLifetime { get; set; }
/// <summary>
/// 通知类型
/// </summary>
public NotificationType NotificationType { get; set; }
@ -53,11 +57,13 @@ namespace LINGYUN.Abp.Notifications
ILocalizableString displayName = null,
ILocalizableString description = null,
NotificationType notificationType = NotificationType.Application,
NotificationLifetime lifetime = NotificationLifetime.Persistent,
bool allowSubscriptionToClients = false)
{
CateGory = category;
DisplayName = displayName ?? new FixedLocalizableString(category);
Description = description;
NotificationLifetime = lifetime;
NotificationType = notificationType;
AllowSubscriptionToClients = allowSubscriptionToClients;

2
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationEventData.cs

@ -10,6 +10,7 @@ namespace LINGYUN.Abp.Notifications
public string Id { get; set; }
public NotificationData Data { get; set; }
public DateTime CreationTime { get; set; }
public NotificationLifetime Lifetime { get; set; }
public NotificationType NotificationType { get; set; }
public NotificationSeverity NotificationSeverity { get; set; }
@ -29,6 +30,7 @@ namespace LINGYUN.Abp.Notifications
Name = Name,
CateGory = CateGory,
NotificationType = NotificationType,
Lifetime = Lifetime,
TenantId = TenantId
};
}

3
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs

@ -10,11 +10,13 @@ namespace LINGYUN.Abp.Notifications
public string Id { get; set; }
public NotificationData Data { get; set; }
public DateTime CreationTime { get; set; }
public NotificationLifetime Lifetime { get; set; }
public NotificationType NotificationType { get; set; }
public NotificationSeverity NotificationSeverity { get; set; }
public NotificationInfo()
{
Data = new NotificationData();
Lifetime = NotificationLifetime.Persistent;
NotificationType = NotificationType.Application;
NotificationSeverity = NotificationSeverity.Info;
@ -47,6 +49,7 @@ namespace LINGYUN.Abp.Notifications
Id = Id,
Name = Name,
CateGory = CateGory,
Lifetime = Lifetime,
NotificationType = NotificationType,
TenantId = TenantId
};

18
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationLifetime.cs

@ -0,0 +1,18 @@
namespace LINGYUN.Abp.Notifications
{
/// <summary>
/// 通知存活时间
/// 发送之后取消用户订阅,类似于微信小程序
/// </summary>
public enum NotificationLifetime
{
/// <summary>
/// 持久化
/// </summary>
Persistent = 0,
/// <summary>
/// 一次性
/// </summary>
OnlyOne = 1
}
}

4
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpMessageServiceNotificationDefinitionProvider.cs

@ -14,11 +14,15 @@ namespace LINGYUN.Abp.MessageService.Notifications
UserNotificationNames.WelcomeToApplication,
L("WelcomeToApplicationNotification"),
L("WelcomeToApplicationNotification"),
notificationType: NotificationType.System,
lifetime: NotificationLifetime.OnlyOne,
allowSubscriptionToClients: true));
context.Add(new NotificationDefinition(
TenantNotificationNames.NewTenantRegistered,
L("NewTenantRegisterdNotification"),
L("NewTenantRegisterdNotification"),
notificationType: NotificationType.System,
lifetime: NotificationLifetime.OnlyOne,
allowSubscriptionToClients: true));
}

5
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs

@ -95,9 +95,7 @@ namespace LINGYUN.Abp.MessageService.Notifications
using (var unitOfWork = _unitOfWorkManager.Begin())
using (CurrentTenant.Change(tenantId))
{
var userSubscribes = await UserSubscribeRepository.GetSubscribesAsync(notificationName);
await UserSubscribeRepository.DeleteUserSubscriptionAsync(userSubscribes);
await UserSubscribeRepository.DeleteUserSubscriptionAsync(notificationName);
await unitOfWork.SaveChangesAsync();
}
@ -122,6 +120,7 @@ namespace LINGYUN.Abp.MessageService.Notifications
using (var unitOfWork = _unitOfWorkManager.Begin())
using (CurrentTenant.Change(tenantId))
{
// TODO:不追踪用户订阅实体?
var userSubscribes = await UserSubscribeRepository.GetSubscribesAsync(notificationName);
var removeUserSubscribes = userSubscribes.Where(us => identifiers.Any(id => id.UserId.Equals(us.UserId)));

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/IUserSubscribeRepository.cs

@ -22,5 +22,7 @@ namespace LINGYUN.Abp.MessageService.Subscriptions
Task InsertUserSubscriptionAsync(IEnumerable<UserSubscribe> userSubscribes);
Task DeleteUserSubscriptionAsync(IEnumerable<UserSubscribe> userSubscribes);
Task DeleteUserSubscriptionAsync(string notificationName);
}
}

6
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs

@ -78,6 +78,12 @@ namespace LINGYUN.Abp.MessageService.Subscriptions
await DbSet.AddRangeAsync(userSubscribes);
}
public async Task DeleteUserSubscriptionAsync(string notificationName)
{
var userSubscribes = await DbSet.Where(x => x.NotificationName.Equals(notificationName)).ToListAsync();
DbSet.RemoveRange(userSubscribes);
}
public Task DeleteUserSubscriptionAsync(IEnumerable<UserSubscribe> userSubscribes)
{
DbSet.RemoveRange(userSubscribes);

7
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs

@ -96,6 +96,13 @@ namespace LINGYUN.Abp.MessageService.EventBus.Distributed
{
await PublishAsync(provider, notificationInfo, subscriptionUserIdentifiers);
}
if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne)
{
// 一次性通知在发送完成后就取消用户订阅
await NotificationStore.DeleteAllUserSubscriptionAsync(notificationInfo.TenantId,
notificationInfo.Name);
}
}
/// <summary>
/// 发布通知

7
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Notifications/MessageServiceDefinitionProvider.cs

@ -2,7 +2,7 @@
using LINGYUN.Abp.Notifications;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.MessageService.LINGYUN.Abp.MessageService.Notifications
namespace LINGYUN.Abp.MessageService.Notifications
{
public class MessageServiceDefinitionProvider : NotificationDefinitionProvider
{
@ -12,8 +12,9 @@ namespace LINGYUN.Abp.MessageService.LINGYUN.Abp.MessageService.Notifications
"TestApplicationNotofication",
L("TestApplicationNotofication"),
L("TestApplicationNotofication"),
NotificationType.Application,
true));
notificationType: NotificationType.Application,
lifetime: NotificationLifetime.OnlyOne,
allowSubscriptionToClients: true));
}
protected LocalizableString L(string name)

Loading…
Cancel
Save