Browse Source

Support for dynamic notification definitions

* Change INotificationDefinitionManager to asynchronous  methods
* Increase IStaticNotificationDefinitionStore interface for users to define static notice
* Increase IDynamicNotificationDefinitionStore interface to get dynamic notification from other source definition
* Increase DynamicNotificationDefinitionStore get dynamic notification from l3 cache
* Add Entity NotificationDefinitionGroupRecord
* Add Repository INotificationDefinitionGroupRecordRepository
* Add Entity NotificationDefinitionRecord
* Add Repository INotificationDefinitionRecordRepository
pull/676/head
cKey 3 years ago
parent
commit
e0aba0f43a
  1. 2
      aspnet-core/LINGYUN.MicroService.All.sln
  2. 6
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/AbpNotificationTemplateDefinitionProvider.cs
  3. 13
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/IDynamicNotificationDefinitionStore.cs
  4. 11
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/INotificationDefinitionManager.cs
  5. 13
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/IStaticNotificationDefinitionStore.cs
  6. 2
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/NotificationDefinition.cs
  7. 157
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/NotificationDefinitionManager.cs
  8. 8
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/NotificationGroupDefinition.cs
  9. 34
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/NullDynamicNotificationDefinitionStore.cs
  10. 101
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/StaticNotificationDefinitionStore.cs
  11. 3
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/IMyNotificationAppService.cs
  12. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/INotificationAppService.cs
  13. 42
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application/LINGYUN/Abp/MessageService/Notifications/MyNotificationAppService.cs
  14. 57
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application/LINGYUN/Abp/MessageService/Notifications/NotificationAppService.cs
  15. 10
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionGroupRecordConsts.cs
  16. 11
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionRecordConsts.cs
  17. 10
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpNotificationsManagementOptions.cs
  18. 287
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/DynamicNotificationDefinitionCache.cs
  19. 50
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/DynamicNotificationDefinitionStore.cs
  20. 14
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IDynamicNotificationDefinitionCache.cs
  21. 8
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationDefinitionGroupRecordRepository.cs
  22. 8
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationDefinitionRecordRepository.cs
  23. 89
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionGroupRecord.cs
  24. 53
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionGroupsCacheItem.cs
  25. 127
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionRecord.cs
  26. 68
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionsCacheItem.cs
  27. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs
  28. 42
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs
  29. 19
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationDefinitionGroupRecordRepository.cs
  30. 19
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationDefinitionRecordRepository.cs
  31. 8
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.HttpApi/LINGYUN/Abp/MessageService/Notifications/MyNotificationController.cs
  32. 7
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.HttpApi/LINGYUN/Abp/MessageService/Notifications/NotificationController.cs
  33. 2
      aspnet-core/modules/pushplus/LINGYUN.Abp.Notifications.PushPlus/LINGYUN/Abp/Notifications/PushPlus/PushPlusNotificationPublishProvider.cs
  34. 2
      aspnet-core/modules/wx-pusher/LINGYUN.Abp.Notifications.WxPusher/LINGYUN/Abp/Notifications/WxPusher/WxPusherNotificationPublishProvider.cs
  35. 5
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs
  36. 720
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Migrations/20220902104049_Add-Dynamic-Notification.Designer.cs
  37. 76
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Migrations/20220902104049_Add-Dynamic-Notification.cs
  38. 90
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Migrations/RealtimeMessageMigrationsDbContextModelSnapshot.cs

2
aspnet-core/LINGYUN.MicroService.All.sln

@ -464,7 +464,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.P
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "realtime", "realtime", "{ECC8B9A9-9E92-4493-984D-2E350A49189D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Core", "modules\common\LINGYUN.Abp.Notifications.Core\LINGYUN.Abp.Notifications.Core.csproj", "{62971DAE-CE71-4E9C-B6F5-514C8E2B915C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Core", "modules\common\LINGYUN.Abp.Notifications.Core\LINGYUN.Abp.Notifications.Core.csproj", "{62971DAE-CE71-4E9C-B6F5-514C8E2B915C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Jobs", "modules\common\LINGYUN.Abp.Notifications.Jobs\LINGYUN.Abp.Notifications.Jobs.csproj", "{3E9D07D8-963C-4A61-B720-BD47593BE752}"
EndProject

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

@ -14,8 +14,10 @@ public class AbpNotificationTemplateDefinitionProvider : TemplateDefinitionProvi
public override void Define(ITemplateDefinitionContext context)
{
var notifications = _notificationDefinitionManager.GetAll().Where(n => n.Template != null);
foreach (var notification in notifications)
var notifications = _notificationDefinitionManager
.GetNotificationsAsync().GetAwaiter().GetResult();
foreach (var notification in notifications.Where(n => n.Template != null))
{
context.Add(notification.Template);
}

13
aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/IDynamicNotificationDefinitionStore.cs

@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Notifications;
public interface IDynamicNotificationDefinitionStore
{
Task<NotificationDefinition> GetOrNullAsync(string name);
Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync();
Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync();
}

11
aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/INotificationDefinitionManager.cs

@ -1,17 +1,18 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Notifications
{
public interface INotificationDefinitionManager
{
[NotNull]
NotificationDefinition Get([NotNull] string name);
Task<NotificationDefinition> GetAsync([NotNull] string name);
IReadOnlyList<NotificationDefinition> GetAll();
Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync();
NotificationDefinition GetOrNull(string name);
Task<NotificationDefinition> GetOrNullAsync(string name);
IReadOnlyList<NotificationGroupDefinition> GetGroups();
Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync();
}
}

13
aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/IStaticNotificationDefinitionStore.cs

@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Notifications;
public interface IStaticNotificationDefinitionStore
{
Task<NotificationDefinition> GetOrNullAsync(string name);
Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync();
Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync();
}

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

@ -83,7 +83,7 @@ namespace LINGYUN.Abp.Notifications
{
if (!providers.IsNullOrEmpty())
{
Providers.AddRange(providers);
Providers.AddIfNotContains(providers);
}
return this;

157
aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/NotificationDefinitionManager.cs

@ -1,111 +1,70 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Notifications
{
public class NotificationDefinitionManager : INotificationDefinitionManager, ISingletonDependency
{
protected AbpNotificationsOptions Options { get; }
protected IDictionary<string, NotificationGroupDefinition> NotificationGroupDefinitions => _lazyNotificationGroupDefinitions.Value;
private readonly Lazy<Dictionary<string, NotificationGroupDefinition>> _lazyNotificationGroupDefinitions;
protected IDictionary<string, NotificationDefinition> NotificationDefinitions => _lazyNotificationDefinitions.Value;
private readonly Lazy<Dictionary<string, NotificationDefinition>> _lazyNotificationDefinitions;
private readonly IServiceScopeFactory _serviceScopeFactory;
public NotificationDefinitionManager(
IOptions<AbpNotificationsOptions> options,
IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
Options = options.Value;
_lazyNotificationDefinitions = new Lazy<Dictionary<string, NotificationDefinition>>(
CreateNotificationDefinitions,
isThreadSafe: true
);
_lazyNotificationGroupDefinitions = new Lazy<Dictionary<string, NotificationGroupDefinition>>(
CreateNotificationGroupDefinitions,
isThreadSafe: true
);
}
public virtual NotificationDefinition Get(string name)
{
Check.NotNull(name, nameof(name));
var feature = GetOrNull(name);
if (feature == null)
{
throw new AbpException("Undefined notification: " + name);
}
return feature;
}
public virtual IReadOnlyList<NotificationDefinition> GetAll()
{
return NotificationDefinitions.Values.ToImmutableList();
public class NotificationDefinitionManager : INotificationDefinitionManager, ITransientDependency
{
private readonly IStaticNotificationDefinitionStore _staticStore;
private readonly IDynamicNotificationDefinitionStore _dynamicStore;
public NotificationDefinitionManager(
IStaticNotificationDefinitionStore staticStore,
IDynamicNotificationDefinitionStore dynamicStore)
{
_staticStore = staticStore;
_dynamicStore = dynamicStore;
}
public virtual NotificationDefinition GetOrNull(string name)
{
return NotificationDefinitions.GetOrDefault(name);
}
public IReadOnlyList<NotificationGroupDefinition> GetGroups()
{
return NotificationGroupDefinitions.Values.ToImmutableList();
}
protected virtual Dictionary<string, NotificationDefinition> CreateNotificationDefinitions()
{
var notifications = new Dictionary<string, NotificationDefinition>();
foreach (var groupDefinition in NotificationGroupDefinitions.Values)
{
foreach (var notification in groupDefinition.Notifications)
{
if (notifications.ContainsKey(notification.Name))
{
throw new AbpException("Duplicate notification name: " + notification.Name);
}
notifications[notification.Name] = notification;
}
}
return notifications;
}
protected virtual Dictionary<string, NotificationGroupDefinition> CreateNotificationGroupDefinitions()
{
var context = new NotificationDefinitionContext();
using (var scope = _serviceScopeFactory.CreateScope())
{
var providers = Options
.DefinitionProviders
.Select(p => scope.ServiceProvider.GetRequiredService(p) as INotificationDefinitionProvider)
.ToList();
foreach (var provider in providers)
{
provider.Define(context);
}
}
return context.Groups;
public virtual async Task<NotificationDefinition> GetAsync(string name)
{
var notification = await GetOrNullAsync(name);
if (notification == null)
{
throw new AbpException("Undefined notification: " + name);
}
return notification;
}
public virtual async Task<NotificationDefinition> GetOrNullAsync(string name)
{
Check.NotNull(name, nameof(name));
return await _staticStore.GetOrNullAsync(name) ??
await _dynamicStore.GetOrNullAsync(name);
}
public virtual async Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync()
{
var staticNotifications = await _staticStore.GetNotificationsAsync();
var staticNotificationNames = staticNotifications
.Select(p => p.Name)
.ToImmutableHashSet();
var dynamicNotifications = await _dynamicStore.GetNotificationsAsync();
return staticNotifications
.Concat(dynamicNotifications.Where(d => !staticNotificationNames.Contains(d.Name)))
.ToImmutableList();
}
public async Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync()
{
var staticGroups = await _staticStore.GetGroupsAsync();
var staticGroupNames = staticGroups
.Select(p => p.Name)
.ToImmutableHashSet();
var dynamicGroups = await _dynamicStore.GetGroupsAsync();
return staticGroups
.Concat(dynamicGroups.Where(d => !staticGroupNames.Contains(d.Name)))
.ToImmutableList();
}
}
}

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

@ -32,6 +32,14 @@ namespace LINGYUN.Abp.Notifications
public IReadOnlyList<NotificationDefinition> Notifications => _notifications.ToImmutableList();
private readonly List<NotificationDefinition> _notifications;
public static NotificationGroupDefinition Create(
string name,
ILocalizableString displayName = null,
bool allowSubscriptionToClients = false)
{
return new NotificationGroupDefinition(name, displayName, allowSubscriptionToClients);
}
protected internal NotificationGroupDefinition(
string name,
ILocalizableString displayName = null,

34
aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/NullDynamicNotificationDefinitionStore.cs

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Notifications;
[Dependency(TryRegister = true)]
public class NullDynamicNotificationDefinitionStore : IDynamicNotificationDefinitionStore, ISingletonDependency
{
private readonly static Task<NotificationDefinition> CachedNotificationResult = Task.FromResult((NotificationDefinition)null);
private readonly static Task<IReadOnlyList<NotificationDefinition>> CachedNotificationsResult =
Task.FromResult((IReadOnlyList<NotificationDefinition>)Array.Empty<NotificationDefinition>().ToImmutableList());
private readonly static Task<IReadOnlyList<NotificationGroupDefinition>> CachedGroupsResult =
Task.FromResult((IReadOnlyList<NotificationGroupDefinition>)Array.Empty<NotificationGroupDefinition>().ToImmutableList());
public Task<NotificationDefinition> GetOrNullAsync(string name)
{
return CachedNotificationResult;
}
public Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync()
{
return CachedNotificationsResult;
}
public Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync()
{
return CachedGroupsResult;
}
}

101
aspnet-core/modules/common/LINGYUN.Abp.Notifications.Core/LINGYUN/Abp/Notifications/StaticNotificationDefinitionStore.cs

@ -0,0 +1,101 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Notifications;
public class StaticNotificationDefinitionStore : IStaticNotificationDefinitionStore, ISingletonDependency
{
protected IDictionary<string, NotificationGroupDefinition> NotificationGroupDefinitions => _lazyNotificationGroupDefinitions.Value;
private readonly Lazy<Dictionary<string, NotificationGroupDefinition>> _lazyNotificationGroupDefinitions;
protected IDictionary<string, NotificationDefinition> NotificationDefinitions => _lazyNotificationDefinitions.Value;
private readonly Lazy<Dictionary<string, NotificationDefinition>> _lazyNotificationDefinitions;
protected AbpNotificationsOptions Options { get; }
private readonly IServiceScopeFactory _serviceScopeFactory;
public StaticNotificationDefinitionStore(
IServiceScopeFactory serviceScopeFactory,
IOptions<AbpNotificationsOptions> options)
{
_serviceScopeFactory = serviceScopeFactory;
Options = options.Value;
_lazyNotificationDefinitions = new Lazy<Dictionary<string, NotificationDefinition>>(
CreateNotificationDefinitions,
isThreadSafe: true
);
_lazyNotificationGroupDefinitions = new Lazy<Dictionary<string, NotificationGroupDefinition>>(
CreateNotificationGroupDefinitions,
isThreadSafe: true
);
}
protected virtual Dictionary<string, NotificationDefinition> CreateNotificationDefinitions()
{
var notifications = new Dictionary<string, NotificationDefinition>();
foreach (var groupDefinition in NotificationGroupDefinitions.Values)
{
foreach (var notification in groupDefinition.Notifications)
{
if (notifications.ContainsKey(notification.Name))
{
throw new AbpException("Duplicate notification name: " + notification.Name);
}
notifications[notification.Name] = notification;
}
}
return notifications;
}
protected virtual Dictionary<string, NotificationGroupDefinition> CreateNotificationGroupDefinitions()
{
var context = new NotificationDefinitionContext();
using (var scope = _serviceScopeFactory.CreateScope())
{
var providers = Options
.DefinitionProviders
.Select(p => scope.ServiceProvider.GetRequiredService(p) as INotificationDefinitionProvider)
.ToList();
foreach (var provider in providers)
{
provider.Define(context);
}
}
return context.Groups;
}
public Task<NotificationDefinition> GetOrNullAsync(string name)
{
return Task.FromResult(NotificationDefinitions.GetOrDefault(name));
}
public virtual Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync()
{
return Task.FromResult<IReadOnlyList<NotificationDefinition>>(
NotificationDefinitions.Values.ToImmutableList()
);
}
public Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync()
{
return Task.FromResult<IReadOnlyList<NotificationGroupDefinition>>(
NotificationGroupDefinitions.Values.ToImmutableList()
);
}
}

3
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/IMyNotificationAppService.cs

@ -1,5 +1,4 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.MessageService.Notifications
@ -14,7 +13,5 @@ namespace LINGYUN.Abp.MessageService.Notifications
IDeleteAppService<long>
{
Task MarkReadStateAsync(NotificationMarkReadStateInput input);
Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync();
}
}

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/INotificationAppService.cs

@ -5,6 +5,8 @@ namespace LINGYUN.Abp.MessageService.Notifications
{
public interface INotificationAppService
{
Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync();
Task<ListResultDto<NotificationTemplateDto>> GetAssignableTemplatesAsync();
Task SendAsync(NotificationSendDto input);

42
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application/LINGYUN/Abp/MessageService/Notifications/MyNotificationAppService.cs

@ -49,48 +49,6 @@ namespace LINGYUN.Abp.MessageService.Notifications
id);
}
public virtual Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync()
{
var groups = new List<NotificationGroupDto>();
foreach (var group in NotificationDefinitionManager.GetGroups())
{
if (!group.AllowSubscriptionToClients)
{
continue;
}
var notificationGroup = new NotificationGroupDto
{
Name = group.Name,
DisplayName = group.DisplayName.Localize(StringLocalizerFactory)
};
foreach (var notification in group.Notifications)
{
if (!notification.AllowSubscriptionToClients)
{
continue;
}
var notificationChildren = new NotificationDto
{
Name = notification.Name,
DisplayName = notification.DisplayName.Localize(StringLocalizerFactory),
Description = notification.Description.Localize(StringLocalizerFactory),
Lifetime = notification.NotificationLifetime,
Type = notification.NotificationType
};
notificationGroup.Notifications.Add(notificationChildren);
}
groups.Add(notificationGroup);
}
return Task.FromResult(new ListResultDto<NotificationGroupDto>(groups));
}
public async virtual Task<UserNotificationDto> GetAsync(long id)
{
var notification = await UserNotificationRepository.GetByIdAsync(CurrentUser.GetId(), id);

57
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application/LINGYUN/Abp/MessageService/Notifications/NotificationAppService.cs

@ -28,10 +28,55 @@ namespace LINGYUN.Abp.MessageService.Notifications
NotificationDefinitionManager = notificationDefinitionManager;
}
public virtual Task<ListResultDto<NotificationTemplateDto>> GetAssignableTemplatesAsync()
public async virtual Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync()
{
var groups = new List<NotificationGroupDto>();
var defineGroups = await NotificationDefinitionManager.GetGroupsAsync();
foreach (var group in defineGroups)
{
if (!group.AllowSubscriptionToClients)
{
continue;
}
var notificationGroup = new NotificationGroupDto
{
Name = group.Name,
DisplayName = group.DisplayName.Localize(StringLocalizerFactory)
};
foreach (var notification in group.Notifications)
{
if (!notification.AllowSubscriptionToClients)
{
continue;
}
var notificationChildren = new NotificationDto
{
Name = notification.Name,
DisplayName = notification.DisplayName.Localize(StringLocalizerFactory),
Description = notification.Description?.Localize(StringLocalizerFactory) ?? notification.Name,
Lifetime = notification.NotificationLifetime,
Type = notification.NotificationType
};
notificationGroup.Notifications.Add(notificationChildren);
}
groups.Add(notificationGroup);
}
return new ListResultDto<NotificationGroupDto>(groups);
}
public async virtual Task<ListResultDto<NotificationTemplateDto>> GetAssignableTemplatesAsync()
{
var templates = new List<NotificationTemplateDto>();
var notifications = NotificationDefinitionManager.GetAll().Where(n => n.Template != null);
var notifications = (await NotificationDefinitionManager
.GetNotificationsAsync())
.Where(n => n.Template != null);
foreach (var notification in notifications)
{
@ -45,12 +90,12 @@ namespace LINGYUN.Abp.MessageService.Notifications
});
}
return Task.FromResult(new ListResultDto<NotificationTemplateDto>(templates));
return new ListResultDto<NotificationTemplateDto>(templates);
}
public async virtual Task SendAsync(NotificationSendDto input)
{
var notification = GetNotificationDefinition(input.Name);
var notification = await GetNotificationDefinition(input.Name);
UserIdentifier user = null;
if (input.ToUserId.HasValue)
@ -71,9 +116,9 @@ namespace LINGYUN.Abp.MessageService.Notifications
input.Severity);
}
protected virtual NotificationDefinition GetNotificationDefinition(string name)
protected async virtual Task<NotificationDefinition> GetNotificationDefinition(string name)
{
var notification = NotificationDefinitionManager.GetOrNull(name);
var notification = await NotificationDefinitionManager.GetOrNullAsync(name);
if (notification == null || notification.Template == null)
{
throw new BusinessException(

10
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionGroupRecordConsts.cs

@ -0,0 +1,10 @@
namespace LINGYUN.Abp.MessageService.Notifications;
public static class NotificationDefinitionGroupRecordConsts
{
public static int MaxNameLength { get; set; } = 64;
public static int MaxDisplayNameLength { get; set; } = 255;
public static int MaxResourceNameLength { get; set; } = 64;
public static int MaxLocalizationLength { get; set; } = 128;
public static int MaxDescriptionLength { get; set; } = 255;
}

11
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionRecordConsts.cs

@ -0,0 +1,11 @@
namespace LINGYUN.Abp.MessageService.Notifications;
public static class NotificationDefinitionRecordConsts
{
public static int MaxNameLength { get; set; } = 64;
public static int MaxDisplayNameLength { get; set; } = 255;
public static int MaxResourceNameLength { get; set; } = 64;
public static int MaxLocalizationLength { get; set; } = 128;
public static int MaxDescriptionLength { get; set; } = 255;
public static int MaxProvidersLength { get; set; } = 200;
}

10
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpNotificationsManagementOptions.cs

@ -0,0 +1,10 @@
namespace LINGYUN.Abp.MessageService.Notifications;
public class AbpNotificationsManagementOptions
{
public bool IsDynamicNotificationStoreEnabled { get; set; }
public AbpNotificationsManagementOptions()
{
IsDynamicNotificationStoreEnabled = true;
}
}

287
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/DynamicNotificationDefinitionCache.cs

@ -0,0 +1,287 @@
using LINGYUN.Abp.Notifications;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.MessageService.Notifications;
public class DynamicNotificationDefinitionCache : IDynamicNotificationDefinitionCache, ISingletonDependency
{
private readonly static ConcurrentDictionary<string, NotificationDefinitionGroupsCacheItem> _dynamicNotificationGroupL1Cache;
private readonly static ConcurrentDictionary<string, NotificationDefinitionsCacheItem> _dynamicNotificationsL1Cache;
private readonly static SemaphoreSlim _l2CacheSyncLock;
protected IMemoryCache DynamicNotificationL2Cache { get; }
protected IDistributedCache<NotificationDefinitionGroupsCacheItem> DynamicNotificationGroupL3Cache { get; }
protected IDistributedCache<NotificationDefinitionsCacheItem> DynamicNotificationsL3Cache { get; }
protected INotificationDefinitionGroupRecordRepository NotificationDefinitionGroupRecordRepository { get; }
protected INotificationDefinitionRecordRepository NotificationDefinitionRecordRepository { get; }
protected AbpLocalizationOptions LocalizationOptions { get; }
protected IStringLocalizerFactory StringLocalizerFactory { get; }
static DynamicNotificationDefinitionCache()
{
_l2CacheSyncLock = new SemaphoreSlim(1, 1);
_dynamicNotificationsL1Cache = new ConcurrentDictionary<string, NotificationDefinitionsCacheItem>();
_dynamicNotificationGroupL1Cache = new ConcurrentDictionary<string, NotificationDefinitionGroupsCacheItem>();
}
public DynamicNotificationDefinitionCache(
IMemoryCache dynamicNotificationL2Cache,
IDistributedCache<NotificationDefinitionGroupsCacheItem> dynamicNotificationGroupL3Cache,
IDistributedCache<NotificationDefinitionsCacheItem> dynamicNotificationsL3Cache,
INotificationDefinitionGroupRecordRepository notificationDefinitionGroupRecordRepository,
INotificationDefinitionRecordRepository notificationDefinitionRecordRepository,
IOptions<AbpLocalizationOptions> localizationOptions,
IStringLocalizerFactory stringLocalizerFactory)
{
DynamicNotificationL2Cache = dynamicNotificationL2Cache;
DynamicNotificationGroupL3Cache = dynamicNotificationGroupL3Cache;
DynamicNotificationsL3Cache = dynamicNotificationsL3Cache;
NotificationDefinitionGroupRecordRepository = notificationDefinitionGroupRecordRepository;
NotificationDefinitionRecordRepository = notificationDefinitionRecordRepository;
LocalizationOptions = localizationOptions.Value;
StringLocalizerFactory = stringLocalizerFactory;
}
public async virtual Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync()
{
var cacheKey = NotificationDefinitionGroupsCacheItem.CalculateCacheKey(CultureInfo.CurrentCulture.Name);
if (!_dynamicNotificationGroupL1Cache.TryGetValue(cacheKey, out var cacheItem))
{
cacheItem = await GetGroupsFormL2CacheAsync(cacheKey);
}
return cacheItem.Groups
.Select(g => NotificationGroupDefinition
.Create(g.Name, new FixedLocalizableString(g.DisplayName), g.AllowSubscriptionToClients))
.ToImmutableList();
}
public async virtual Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync()
{
var cacheKey = NotificationDefinitionsCacheItem.CalculateCacheKey(CultureInfo.CurrentCulture.Name);
if (!_dynamicNotificationsL1Cache.TryGetValue(cacheKey, out var cacheItem))
{
cacheItem = await GetNotificationsFormL2CacheAsync(cacheKey);
}
return cacheItem.Notifications
.Select(n => new NotificationDefinition(
n.Name,
new FixedLocalizableString(n.DisplayName),
new FixedLocalizableString(n.Description),
n.NotificationType,
n.Lifetime,
n.AllowSubscriptionToClients))
.ToImmutableList();
}
public async virtual Task<NotificationDefinition> GetOrNullAsync(string name)
{
var notifications = await GetNotificationsAsync();
return notifications.FirstOrDefault(n => n.Name.Equals(name));
}
protected async virtual Task<NotificationDefinitionGroupsCacheItem> GetGroupsFormL2CacheAsync(string cacheKey)
{
var cacheItem = DynamicNotificationL2Cache.Get<NotificationDefinitionGroupsCacheItem>(cacheKey);
if (cacheItem == null)
{
using (await _l2CacheSyncLock.LockAsync())
{
var l2cache = await GetGroupsFormL3CacheAsync(cacheKey);
var options = new MemoryCacheEntryOptions();
options.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
options.SetPriority(CacheItemPriority.High);
options.RegisterPostEvictionCallback((key, value, reason, state) =>
{
_dynamicNotificationGroupL1Cache.Clear();
});
DynamicNotificationL2Cache.Set(cacheKey, l2cache, options);
return l2cache;
}
}
return cacheItem;
}
protected async virtual Task<NotificationDefinitionGroupsCacheItem> GetGroupsFormL3CacheAsync(string cacheKey)
{
var cacheItem = await DynamicNotificationGroupL3Cache.GetAsync(cacheKey);
if (cacheItem == null)
{
var records = await GetGroupsFormRepositoryAsync();
var recordCaches = new List<NotificationDefinitionGroupCacheItem>();
foreach (var record in records)
{
var displayName = record.DisplayName;
var description = record.Description;
if (!record.ResourceName.IsNullOrWhiteSpace() && !record.Localization.IsNullOrWhiteSpace())
{
var resource = GetResourceOrNull(record.ResourceName);
if (resource != null)
{
var localizer = StringLocalizerFactory.Create(resource.ResourceType);
displayName = localizer[$"DisplayName:{record.Localization}"];
description = localizer[$"Description:{record.Localization}"];
}
}
recordCaches.Add(new NotificationDefinitionGroupCacheItem(
record.Name,
displayName,
description,
record.AllowSubscriptionToClients));
}
cacheItem = new NotificationDefinitionGroupsCacheItem(recordCaches.ToArray());
await DynamicNotificationGroupL3Cache.SetAsync(
cacheKey,
cacheItem,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(2),
SlidingExpiration = TimeSpan.FromHours(1),
});
}
return cacheItem;
}
protected async virtual Task<List<NotificationDefinitionGroupRecord>> GetGroupsFormRepositoryAsync()
{
var records = await NotificationDefinitionGroupRecordRepository.GetListAsync();
return records;
}
protected async virtual Task<NotificationDefinitionsCacheItem> GetNotificationsFormL2CacheAsync(string cacheKey)
{
var cacheItem = DynamicNotificationL2Cache.Get<NotificationDefinitionsCacheItem>(cacheKey);
if (cacheItem == null)
{
using (await _l2CacheSyncLock.LockAsync())
{
var l2cache = await GetNotificationsFormL3CacheAsync(cacheKey);
var options = new MemoryCacheEntryOptions();
options.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
options.SetPriority(CacheItemPriority.High);
options.RegisterPostEvictionCallback((key, value, reason, state) =>
{
_dynamicNotificationsL1Cache.Clear();
});
DynamicNotificationL2Cache.Set(cacheKey, l2cache, options);
return l2cache;
}
}
return cacheItem;
}
protected async virtual Task<NotificationDefinitionsCacheItem> GetNotificationsFormL3CacheAsync(string cacheKey)
{
var cacheItem = await DynamicNotificationsL3Cache.GetAsync(cacheKey);
if (cacheItem == null)
{
var records = await GetNotificationsFormRepositoryAsync();
var recordCaches = new List<NotificationDefinitionCacheItem>();
foreach (var record in records)
{
var displayName = record.Name;
var description = record.Name;
var providers = new List<string>();
if (!record.Providers.IsNullOrWhiteSpace())
{
providers = record.Providers.Split(';').ToList();
}
if (record.ResourceName.IsNullOrWhiteSpace() && record.Localization.IsNullOrWhiteSpace())
{
var resource = GetResourceOrNull(record.ResourceName);
if (resource != null)
{
var localizer = StringLocalizerFactory.Create(resource.ResourceType);
displayName = localizer[$"DisplayName:{record.Localization}"];
description = localizer[$"Description:{record.Localization}"];
}
}
var recordCache = new NotificationDefinitionCacheItem(
record.Name,
displayName,
description,
record.NotificationLifetime,
record.NotificationType,
providers,
record.AllowSubscriptionToClients);
recordCache.Properties.AddIfNotContains(record.ExtraProperties);
recordCaches.Add(recordCache);
}
cacheItem = new NotificationDefinitionsCacheItem(recordCaches.ToArray());
await DynamicNotificationsL3Cache.SetAsync(
cacheKey,
cacheItem,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(2),
SlidingExpiration = TimeSpan.FromHours(1),
});
}
return cacheItem;
}
protected async virtual Task<List<NotificationDefinitionRecord>> GetNotificationsFormRepositoryAsync()
{
var records = await NotificationDefinitionRecordRepository.GetListAsync();
return records;
}
protected virtual LocalizationResource GetResourceOrNull(string resourceName)
{
return LocalizationOptions.Resources.Values
.FirstOrDefault(x => x.ResourceName.Equals(resourceName));
}
}

50
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/DynamicNotificationDefinitionStore.cs

@ -0,0 +1,50 @@
using LINGYUN.Abp.Notifications;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.MessageService.Notifications;
[Dependency(ReplaceServices = true)]
public class DynamicNotificationDefinitionStore : IDynamicNotificationDefinitionStore, ITransientDependency
{
private readonly AbpNotificationsManagementOptions _notificationsManagementOptions;
private readonly IDynamicNotificationDefinitionCache _dynamicNotificationDefinitionCache;
public DynamicNotificationDefinitionStore(
IDynamicNotificationDefinitionCache dynamicNotificationDefinitionCache,
IOptions<AbpNotificationsManagementOptions> notificationsManagementOptions)
{
_dynamicNotificationDefinitionCache = dynamicNotificationDefinitionCache;
_notificationsManagementOptions = notificationsManagementOptions.Value;
}
public async virtual Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync()
{
if (!_notificationsManagementOptions.IsDynamicNotificationStoreEnabled)
{
return Array.Empty<NotificationGroupDefinition>();
}
return await _dynamicNotificationDefinitionCache.GetGroupsAsync();
}
public async virtual Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync()
{
if (!_notificationsManagementOptions.IsDynamicNotificationStoreEnabled)
{
return Array.Empty<NotificationDefinition>();
}
return await _dynamicNotificationDefinitionCache.GetNotificationsAsync();
}
public async virtual Task<NotificationDefinition> GetOrNullAsync(string name)
{
if (!_notificationsManagementOptions.IsDynamicNotificationStoreEnabled)
{
return null;
}
return await _dynamicNotificationDefinitionCache.GetOrNullAsync(name);
}
}

14
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IDynamicNotificationDefinitionCache.cs

@ -0,0 +1,14 @@
using LINGYUN.Abp.Notifications;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.MessageService.Notifications;
public interface IDynamicNotificationDefinitionCache
{
Task<NotificationDefinition> GetOrNullAsync(string name);
Task<IReadOnlyList<NotificationDefinition>> GetNotificationsAsync();
Task<IReadOnlyList<NotificationGroupDefinition>> GetGroupsAsync();
}

8
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationDefinitionGroupRecordRepository.cs

@ -0,0 +1,8 @@
using System;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Notifications;
public interface INotificationDefinitionGroupRecordRepository : IBasicRepository<NotificationDefinitionGroupRecord, Guid>
{
}

8
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationDefinitionRecordRepository.cs

@ -0,0 +1,8 @@
using System;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Notifications;
public interface INotificationDefinitionRecordRepository : IBasicRepository<NotificationDefinitionRecord, Guid>
{
}

89
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionGroupRecord.cs

@ -0,0 +1,89 @@
using System;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.MessageService.Notifications;
public class NotificationDefinitionGroupRecord : BasicAggregateRoot<Guid>, IHasExtraProperties
{
/// <summary>
/// 分组名称
/// </summary>
public virtual string Name { get; set; }
/// <summary>
/// 显示名称
/// </summary>
/// <remarks>
/// 如果为空,回退到Name
/// </remarks>
public virtual string DisplayName { get; set; }
/// <summary>
/// 描述
/// </summary>
/// <remarks>
/// 如果为空,回退到Name
/// </remarks>
public virtual string Description { get; set; }
/// <summary>
/// 资源名称
/// </summary>
/// <remarks>
/// 如果不为空,作为参与本地化资源的名称
/// DisplayName = L["DisplayName:Localization"]
/// Description = L["Description:Localization"]
/// </remarks>
public virtual string ResourceName { get; protected set; }
/// <summary>
/// 本地化键值名称
/// </summary>
/// <remarks>
/// 如果不为空,作为参与本地化键值的名称
/// DisplayName = L["DisplayName:Localization"]
/// Description = L["Description:Localization"]
/// </remarks>
public virtual string Localization { get; protected set; }
/// <summary>
/// 允许客户端订阅
/// </summary>
public virtual bool AllowSubscriptionToClients { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; protected set; }
public NotificationDefinitionGroupRecord()
{
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
}
public NotificationDefinitionGroupRecord(
Guid id,
string name,
string displayName = null,
string description = null,
string resourceName = null,
string localization = null)
: base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), NotificationDefinitionGroupRecordConsts.MaxNameLength);
DisplayName = Check.Length(displayName, nameof(displayName), NotificationDefinitionGroupRecordConsts.MaxDisplayNameLength);
Description = Check.Length(description, nameof(description), NotificationDefinitionGroupRecordConsts.MaxDescriptionLength);
SetLocalization(resourceName, localization);
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
AllowSubscriptionToClients = true;
}
/// <summary>
/// 设置本地化资源
/// </summary>
/// <param name="resourceName"></param>
/// <param name="localization"></param>
public void SetLocalization(string resourceName, string localization)
{
ResourceName = Check.Length(resourceName, nameof(resourceName), NotificationDefinitionGroupRecordConsts.MaxResourceNameLength);
Localization = Check.Length(localization, nameof(localization), NotificationDefinitionGroupRecordConsts.MaxLocalizationLength);
}
}

53
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionGroupsCacheItem.cs

@ -0,0 +1,53 @@
using System;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Notifications;
[Serializable]
[IgnoreMultiTenancy]
public class NotificationDefinitionGroupsCacheItem
{
private const string CacheKeyFormat = "n:Abp_Notifications_Groups;c:{0}";
public NotificationDefinitionGroupCacheItem[] Groups { get; set; }
public NotificationDefinitionGroupsCacheItem()
{
Groups = new NotificationDefinitionGroupCacheItem[0];
}
public NotificationDefinitionGroupsCacheItem(
NotificationDefinitionGroupCacheItem[] groups)
{
Groups = groups;
}
public static string CalculateCacheKey(string culture)
{
return string.Format(CacheKeyFormat, culture);
}
}
public class NotificationDefinitionGroupCacheItem
{
public string Name { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public bool AllowSubscriptionToClients { get; set; }
public NotificationDefinitionGroupCacheItem()
{
}
public NotificationDefinitionGroupCacheItem(
string name,
string displayName = null,
string description = null,
bool allowSubscriptionToClients = false)
{
Name = name;
DisplayName = displayName;
Description = description;
AllowSubscriptionToClients = allowSubscriptionToClients;
}
}

127
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionRecord.cs

@ -0,0 +1,127 @@
using LINGYUN.Abp.Notifications;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.MessageService.Notifications;
public class NotificationDefinitionRecord : BasicAggregateRoot<Guid>, IHasExtraProperties
{
/// <summary>
/// 名称
/// </summary>
public virtual string Name { get; set; }
/// <summary>
/// 显示名称
/// </summary>
/// <remarks>
/// 如果为空,回退到Name
/// </remarks>
public virtual string DisplayName { get; set; }
/// <summary>
/// 描述
/// </summary>
/// <remarks>
/// 如果为空,回退到Name
/// </remarks>
public virtual string Description { get; set; }
/// <summary>
/// 资源名称
/// </summary>
/// <remarks>
/// 如果不为空,作为参与本地化资源的名称
/// DisplayName = L["DisplayName:Localization"]
/// Description = L["Description:Localization"]
/// </remarks>
public virtual string ResourceName { get; protected set; }
/// <summary>
/// 本地化键值名称
/// </summary>
/// <remarks>
/// 如果不为空,作为参与本地化键值的名称
/// DisplayName = L["DisplayName:Localization"]
/// Description = L["Description:Localization"]
/// </remarks>
public virtual string Localization { get; protected set; }
/// <summary>
/// 存活类型
/// </summary>
public virtual NotificationLifetime NotificationLifetime { get; set; }
/// <summary>
/// 通知类型
/// </summary>
public virtual NotificationType NotificationType { get; set; }
/// <summary>
/// 通知提供者
/// </summary>
/// <remarks>
/// 多个之间用;分隔
/// </remarks>
public virtual string Providers { get; protected set; }
/// <summary>
/// 允许客户端订阅
/// </summary>
public virtual bool AllowSubscriptionToClients { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; protected set; }
public NotificationDefinitionRecord()
{
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
}
public NotificationDefinitionRecord(
Guid id,
string name,
string displayName = null,
string description = null,
string resourceName = null,
string localization = null,
NotificationLifetime lifetime = NotificationLifetime.Persistent,
NotificationType notificationType = NotificationType.Application)
: base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), NotificationDefinitionRecordConsts.MaxNameLength);
DisplayName = Check.Length(displayName, nameof(displayName), NotificationDefinitionRecordConsts.MaxDisplayNameLength);
Description = Check.Length(description, nameof(description), NotificationDefinitionRecordConsts.MaxDescriptionLength);
NotificationLifetime = lifetime;
NotificationType = notificationType;
SetLocalization(resourceName, localization);
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
AllowSubscriptionToClients = true;
}
/// <summary>
/// 设置本地化资源
/// </summary>
/// <param name="resourceName"></param>
/// <param name="localization"></param>
public void SetLocalization(string resourceName, string localization)
{
ResourceName = Check.Length(resourceName, nameof(resourceName), NotificationDefinitionGroupRecordConsts.MaxResourceNameLength);
Localization = Check.Length(localization, nameof(localization), NotificationDefinitionGroupRecordConsts.MaxLocalizationLength);
}
public void UseProviders(params string[] providers)
{
var currentProviders = Providers.IsNullOrWhiteSpace()
? new List<string>()
: Providers.Split(';').ToList();
if (!providers.IsNullOrEmpty())
{
currentProviders.AddIfNotContains(providers);
}
if (currentProviders.Any())
{
Providers = currentProviders.JoinAsString(";");
}
}
}

68
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDefinitionsCacheItem.cs

@ -0,0 +1,68 @@
using LINGYUN.Abp.Notifications;
using System;
using System.Collections.Generic;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Notifications;
[Serializable]
[IgnoreMultiTenancy]
public class NotificationDefinitionsCacheItem
{
private const string CacheKeyFormat = "n:Abp_Notifications;c:{0}";
public NotificationDefinitionCacheItem[] Notifications { get; set; }
public NotificationDefinitionsCacheItem()
{
Notifications = new NotificationDefinitionCacheItem[0];
}
public NotificationDefinitionsCacheItem(
NotificationDefinitionCacheItem[] notifications)
{
Notifications = notifications;
}
public static string CalculateCacheKey(string culture)
{
return string.Format(CacheKeyFormat, culture);
}
}
public class NotificationDefinitionCacheItem
{
public string Name { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public NotificationLifetime Lifetime { get; set; }
public NotificationType NotificationType { get; set; }
public List<string> Providers { get; set; }
public bool AllowSubscriptionToClients { get; set; }
public Dictionary<string, object> Properties { get; set; }
public NotificationDefinitionCacheItem()
{
Providers = new List<string>();
Properties = new Dictionary<string, object>();
}
public NotificationDefinitionCacheItem(
string name,
string displayName = null,
string description = null,
NotificationLifetime lifetime = NotificationLifetime.Persistent,
NotificationType notificationType = NotificationType.Application,
List<string> providers = null,
bool allowSubscriptionToClients = false)
{
Name = name;
DisplayName = displayName;
Description = description;
Lifetime = lifetime;
NotificationType = notificationType;
Providers = providers ?? new List<string>();
AllowSubscriptionToClients = allowSubscriptionToClients;
Properties = new Dictionary<string, object>();
}
}

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs

@ -18,6 +18,8 @@ namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
context.Services.AddAbpDbContext<MessageServiceDbContext>(options =>
{
options.AddRepository<Notification, EfCoreNotificationRepository>();
options.AddRepository<NotificationDefinitionRecord, EfCoreNotificationDefinitionRecordRepository>();
options.AddRepository<NotificationDefinitionGroupRecord, EfCoreNotificationDefinitionGroupRecordRepository>();
options.AddRepository<UserNotification, EfCoreUserNotificationRepository>();
options.AddRepository<UserSubscribe, EfCoreUserSubscribeRepository>();

42
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs

@ -186,6 +186,48 @@ namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
b.HasIndex(p => new { p.TenantId, p.GroupId, p.UserId });
});
builder.Entity<NotificationDefinitionGroupRecord>(b =>
{
b.ToTable(options.TablePrefix + "NotificationDefinitionGroups", options.Schema);
b.Property(p => p.Name)
.HasMaxLength(NotificationDefinitionGroupRecordConsts.MaxNameLength)
.IsRequired();
b.Property(p => p.DisplayName)
.HasMaxLength(NotificationDefinitionGroupRecordConsts.MaxDisplayNameLength);
b.Property(p => p.Description)
.HasMaxLength(NotificationDefinitionGroupRecordConsts.MaxDescriptionLength);
b.Property(p => p.ResourceName)
.HasMaxLength(NotificationDefinitionGroupRecordConsts.MaxResourceNameLength);
b.Property(p => p.Localization)
.HasMaxLength(NotificationDefinitionGroupRecordConsts.MaxLocalizationLength);
b.ConfigureByConvention();
});
builder.Entity<NotificationDefinitionRecord>(b =>
{
b.ToTable(options.TablePrefix + "NotificationDefinitions", options.Schema);
b.Property(p => p.Name)
.HasMaxLength(NotificationDefinitionRecordConsts.MaxNameLength)
.IsRequired();
b.Property(p => p.DisplayName)
.HasMaxLength(NotificationDefinitionRecordConsts.MaxDisplayNameLength);
b.Property(p => p.Description)
.HasMaxLength(NotificationDefinitionRecordConsts.MaxDescriptionLength);
b.Property(p => p.ResourceName)
.HasMaxLength(NotificationDefinitionRecordConsts.MaxResourceNameLength);
b.Property(p => p.Localization)
.HasMaxLength(NotificationDefinitionRecordConsts.MaxLocalizationLength);
b.Property(p => p.Providers)
.HasMaxLength(NotificationDefinitionRecordConsts.MaxProvidersLength);
b.ConfigureByConvention();
});
}
}
}

19
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationDefinitionGroupRecordRepository.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using System;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.Notifications;
public class EfCoreNotificationDefinitionGroupRecordRepository :
EfCoreRepository<IMessageServiceDbContext, NotificationDefinitionGroupRecord, Guid>,
INotificationDefinitionGroupRecordRepository,
ITransientDependency
{
public EfCoreNotificationDefinitionGroupRecordRepository(
IDbContextProvider<IMessageServiceDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}

19
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationDefinitionRecordRepository.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using System;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.Notifications;
public class EfCoreNotificationDefinitionRecordRepository :
EfCoreRepository<IMessageServiceDbContext, NotificationDefinitionRecord, Guid>,
INotificationDefinitionRecordRepository,
ITransientDependency
{
public EfCoreNotificationDefinitionRecordRepository(
IDbContextProvider<IMessageServiceDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}

8
aspnet-core/modules/message/LINGYUN.Abp.MessageService.HttpApi/LINGYUN/Abp/MessageService/Notifications/MyNotificationController.cs

@ -31,13 +31,7 @@ namespace LINGYUN.Abp.MessageService.Notifications
{
await MyNotificationAppService.DeleteAsync(id);
}
[HttpGet]
[Route("assignables")]
public async virtual Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync()
{
return await MyNotificationAppService.GetAssignableNotifiersAsync();
}
[HttpGet]
[Route("{id}")]

7
aspnet-core/modules/message/LINGYUN.Abp.MessageService.HttpApi/LINGYUN/Abp/MessageService/Notifications/NotificationController.cs

@ -26,6 +26,13 @@ namespace LINGYUN.Abp.MessageService.Notifications
await NotificationAppService.SendAsync(input);
}
[HttpGet]
[Route("assignables")]
public async virtual Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync()
{
return await NotificationAppService.GetAssignableNotifiersAsync();
}
[HttpGet]
[Route("assignable-templates")]
public async virtual Task<ListResultDto<NotificationTemplateDto>> GetAssignableTemplatesAsync()

2
aspnet-core/modules/pushplus/LINGYUN.Abp.Notifications.PushPlus/LINGYUN/Abp/Notifications/PushPlus/PushPlusNotificationPublishProvider.cs

@ -65,7 +65,7 @@ public class PushPlusNotificationPublishProvider : NotificationPublishProvider
{
var topic = "";
var notificationDefine = NotificationDefinitionManager.GetOrNull(notification.Name);
var notificationDefine = await NotificationDefinitionManager.GetOrNullAsync(notification.Name);
var topicDefine = notificationDefine?.GetTopicOrNull();
if (!topicDefine.IsNullOrWhiteSpace())
{

2
aspnet-core/modules/wx-pusher/LINGYUN.Abp.Notifications.WxPusher/LINGYUN/Abp/Notifications/WxPusher/WxPusherNotificationPublishProvider.cs

@ -72,7 +72,7 @@ public class WxPusherNotificationPublishProvider : NotificationPublishProvider
var topics = await WxPusherUserStore.GetSubscribeTopicsAsync(subscribeUserIds, cancellationToken);
var uids = await WxPusherUserStore.GetBindUidsAsync(subscribeUserIds, cancellationToken);
var notificationDefine = NotificationDefinitionManager.GetOrNull(notification.Name);
var notificationDefine = await NotificationDefinitionManager.GetOrNullAsync(notification.Name);
var url = notification.Data.GetUrlOrNull() ?? notificationDefine?.GetUrlOrNull();
var topicDefine = notificationDefine?.GetTopics();
if (topicDefine.Any())

5
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs

@ -109,7 +109,7 @@ namespace LY.MicroService.RealtimeMessage.EventBus.Distributed
{
using (CurrentTenant.Change(eventData.TenantId))
{
var notification = NotificationDefinitionManager.GetOrNull(eventData.Name);
var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name);
if (notification == null)
{
return;
@ -177,8 +177,7 @@ namespace LY.MicroService.RealtimeMessage.EventBus.Distributed
{
using (CurrentTenant.Change(eventData.TenantId))
{
// 如果上面过滤了应用程序,这里可以使用Get方法,否则,最好使用GetOrNull加以判断
var notification = NotificationDefinitionManager.GetOrNull(eventData.Name);
var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name);
if (notification == null)
{
return;

720
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Migrations/20220902104049_Add-Dynamic-Notification.Designer.cs

@ -0,0 +1,720 @@
// <auto-generated />
using System;
using LY.MicroService.RealtimeMessage.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
#nullable disable
namespace LY.MicroService.RealtimeMessage.Migrations
{
[DbContext(typeof(RealtimeMessageMigrationsDbContext))]
[Migration("20220902104049_Add-Dynamic-Notification")]
partial class AddDynamicNotification
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "6.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatCard", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<int>("Age")
.HasColumnType("int");
b.Property<string>("AvatarUrl")
.HasMaxLength(512)
.HasColumnType("varchar(512)");
b.Property<DateTime?>("Birthday")
.HasColumnType("datetime(6)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Description")
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<DateTime?>("LastOnlineTime")
.HasColumnType("datetime(6)");
b.Property<string>("NickName")
.HasMaxLength(256)
.HasColumnType("varchar(256)");
b.Property<int>("Sex")
.HasColumnType("int");
b.Property<string>("Sign")
.HasMaxLength(30)
.HasColumnType("varchar(30)");
b.Property<int>("State")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("varchar(256)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserChatCards", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatFriend", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("Black")
.HasColumnType("tinyint(1)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Description")
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<bool>("DontDisturb")
.HasColumnType("tinyint(1)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<Guid>("FrientId")
.HasColumnType("char(36)");
b.Property<bool>("IsStatic")
.HasColumnType("tinyint(1)");
b.Property<string>("RemarkName")
.HasMaxLength(256)
.HasColumnType("varchar(256)");
b.Property<bool>("SpecialFocus")
.HasColumnType("tinyint(1)");
b.Property<byte>("Status")
.HasColumnType("tinyint unsigned");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "FrientId");
b.ToTable("AppUserChatFriends", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatSetting", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("AllowAddFriend")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowAnonymous")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowReceiveMessage")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendMessage")
.HasColumnType("tinyint(1)");
b.Property<bool>("RequireAddFriendValition")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserChatSettings", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserMessage", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.IsRequired()
.HasMaxLength(1048576)
.HasColumnType("longtext");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<long>("MessageId")
.HasColumnType("bigint");
b.Property<Guid>("ReceiveUserId")
.HasColumnType("char(36)");
b.Property<string>("SendUserName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<int>("Source")
.HasColumnType("int");
b.Property<sbyte>("State")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "ReceiveUserId");
b.ToTable("AppUserMessages", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.ChatGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Address")
.HasMaxLength(256)
.HasColumnType("varchar(256)");
b.Property<Guid>("AdminUserId")
.HasColumnType("char(36)");
b.Property<bool>("AllowAnonymous")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendMessage")
.HasColumnType("tinyint(1)");
b.Property<string>("AvatarUrl")
.HasMaxLength(128)
.HasColumnType("varchar(128)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Description")
.HasMaxLength(128)
.HasColumnType("varchar(128)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<int>("MaxUserCount")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<string>("Notice")
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<string>("Tag")
.HasMaxLength(512)
.HasColumnType("varchar(512)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("TenantId", "Name");
b.ToTable("AppChatGroups", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.GroupChatBlack", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<Guid>("ShieldUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppGroupChatBlacks", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.GroupMessage", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.IsRequired()
.HasMaxLength(1048576)
.HasColumnType("longtext");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<long>("MessageId")
.HasColumnType("bigint");
b.Property<string>("SendUserName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<int>("Source")
.HasColumnType("int");
b.Property<sbyte>("State")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppGroupMessages", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.UserChatGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId", "UserId");
b.ToTable("AppUserChatGroups", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Groups.UserGroupCard", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsAdmin")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("NickName")
.HasMaxLength(256)
.HasColumnType("varchar(256)");
b.Property<DateTime?>("SilenceEnd")
.HasColumnType("datetime(6)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserGroupCards", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("datetime(6)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<string>("NotificationName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("NotificationTypeName")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("varchar(512)");
b.Property<sbyte>("Severity")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "NotificationName");
b.ToTable("AppNotifications", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.NotificationDefinitionGroupRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowSubscriptionToClients")
.HasColumnType("tinyint(1)");
b.Property<string>("Description")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("DisplayName")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<string>("Localization")
.HasMaxLength(128)
.HasColumnType("varchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<string>("ResourceName")
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.HasKey("Id");
b.ToTable("AppNotificationDefinitionGroups", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.NotificationDefinitionRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowSubscriptionToClients")
.HasColumnType("tinyint(1)");
b.Property<string>("Description")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("DisplayName")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<string>("Localization")
.HasMaxLength(128)
.HasColumnType("varchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<int>("NotificationLifetime")
.HasColumnType("int");
b.Property<int>("NotificationType")
.HasColumnType("int");
b.Property<string>("Providers")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("ResourceName")
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.HasKey("Id");
b.ToTable("AppNotificationDefinitions", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<int>("ReadStatus")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationId")
.HasDatabaseName("IX_Tenant_User_Notification_Id");
b.ToTable("AppUserNotifications", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<string>("NotificationName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.Property<string>("UserName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(128)
.HasColumnType("varchar(128)")
.HasDefaultValue("/");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationName")
.IsUnique()
.HasDatabaseName("IX_Tenant_User_Notification_Name");
b.ToTable("AppUserSubscribes", (string)null);
});
#pragma warning restore 612, 618
}
}
}

76
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Migrations/20220902104049_Add-Dynamic-Notification.cs

@ -0,0 +1,76 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LY.MicroService.RealtimeMessage.Migrations
{
public partial class AddDynamicNotification : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AppNotificationDefinitionGroups",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ResourceName = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Localization = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
AllowSubscriptionToClients = table.Column<bool>(type: "tinyint(1)", nullable: false),
ExtraProperties = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_AppNotificationDefinitionGroups", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AppNotificationDefinitions",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ResourceName = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Localization = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NotificationLifetime = table.Column<int>(type: "int", nullable: false),
NotificationType = table.Column<int>(type: "int", nullable: false),
Providers = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
AllowSubscriptionToClients = table.Column<bool>(type: "tinyint(1)", nullable: false),
ExtraProperties = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_AppNotificationDefinitions", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AppNotificationDefinitionGroups");
migrationBuilder.DropTable(
name: "AppNotificationDefinitions");
}
}
}

90
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Migrations/RealtimeMessageMigrationsDbContextModelSnapshot.cs

@ -18,7 +18,7 @@ namespace LY.MicroService.RealtimeMessage.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "5.0.12")
.HasAnnotation("ProductVersion", "6.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.MessageService.Chat.UserChatCard", b =>
@ -560,6 +560,94 @@ namespace LY.MicroService.RealtimeMessage.Migrations
b.ToTable("AppNotifications", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.NotificationDefinitionGroupRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowSubscriptionToClients")
.HasColumnType("tinyint(1)");
b.Property<string>("Description")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("DisplayName")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<string>("Localization")
.HasMaxLength(128)
.HasColumnType("varchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<string>("ResourceName")
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.HasKey("Id");
b.ToTable("AppNotificationDefinitionGroups", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.NotificationDefinitionRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowSubscriptionToClients")
.HasColumnType("tinyint(1)");
b.Property<string>("Description")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("DisplayName")
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<string>("Localization")
.HasMaxLength(128)
.HasColumnType("varchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.Property<int>("NotificationLifetime")
.HasColumnType("int");
b.Property<int>("NotificationType")
.HasColumnType("int");
b.Property<string>("Providers")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("ResourceName")
.HasMaxLength(64)
.HasColumnType("varchar(64)");
b.HasKey("Id");
b.ToTable("AppNotificationDefinitions", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b =>
{
b.Property<long>("Id")

Loading…
Cancel
Save