diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 000000000..e23d5cfc9 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,7 @@ +{ + "ExpandedNodes": [ + "" + ], + "SelectedNode": "\\D:\\Projects\\MicroService\\CRM\\Vue\\vue-abp", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index f8debc5aa..3963a2ce9 100644 Binary files a/.vs/slnx.sqlite and b/.vs/slnx.sqlite differ diff --git a/aspnet-core/LINGYUN.MicroService.Messages.sln b/aspnet-core/LINGYUN.MicroService.Messages.sln index a3daf872b..be9e5a1a2 100644 --- a/aspnet-core/LINGYUN.MicroService.Messages.sln +++ b/aspnet-core/LINGYUN.MicroService.Messages.sln @@ -53,17 +53,23 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProg EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms", "modules\common\LINGYUN.Abp.Notifications.Sms\LINGYUN.Abp.Notifications.Sms.csproj", "{454059F7-D087-439A-A724-80BDFE94776F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj", "{64E2622A-611D-4056-9497-0B52A91DC59C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj", "{64E2622A-611D-4056-9497-0B52A91DC59C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{42800C56-9473-4B96-BF29-1B0F25C867F4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Sms.Tests", "tests\LINGYUN.Abp.Notifications.Sms.Tests\LINGYUN.Abp.Notifications.Sms.Tests.csproj", "{5714481A-BDF5-4860-9158-3B18D3018EC5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms.Tests", "tests\LINGYUN.Abp.Notifications.Sms.Tests\LINGYUN.Abp.Notifications.Sms.Tests.csproj", "{5714481A-BDF5-4860-9158-3B18D3018EC5}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{B5E23AED-3068-4CFE-84B0-3B7725665506}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Tests", "tests\LINGYUN.Abp.Notifications.Tests\LINGYUN.Abp.Notifications.Tests.csproj", "{E5257008-A0AD-473F-91B0-864FC601B84B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Tests", "tests\LINGYUN.Abp.Notifications.Tests\LINGYUN.Abp.Notifications.Tests.csproj", "{E5257008-A0AD-473F-91B0-864FC601B84B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests", "tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests.csproj", "{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests", "tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests.csproj", "{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{25267137-08BE-44A6-9F7E-7783CC8C62E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj", "{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MessageService.Domain.Tests", "tests\LINGYUN.Abp.MessageService.Domain.Tests\LINGYUN.Abp.MessageService.Domain.Tests.csproj", "{097319B9-D062-4A54-8F8C-001C180E2CB3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -171,6 +177,18 @@ Global {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.Build.0 = Release|Any CPU + {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.Build.0 = Release|Any CPU + {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.Build.0 = Release|Any CPU + {097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -204,6 +222,9 @@ Global {B5E23AED-3068-4CFE-84B0-3B7725665506} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {E5257008-A0AD-473F-91B0-864FC601B84B} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7} = {42800C56-9473-4B96-BF29-1B0F25C867F4} + {25267137-08BE-44A6-9F7E-7783CC8C62E8} = {42800C56-9473-4B96-BF29-1B0F25C867F4} + {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F} = {42800C56-9473-4B96-BF29-1B0F25C867F4} + {097319B9-D062-4A54-8F8C-001C180E2CB3} = {42800C56-9473-4B96-BF29-1B0F25C867F4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6238659A-7267-49B9-A499-8746BDEED6B8} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LICENSE.txt b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LICENSE.txt index e62cd50c0..5e48277d6 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LICENSE.txt +++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LICENSE.txt @@ -21,4 +21,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ģԴ +https://github.com/dotnetcore/CAP https://github.com/EasyAbp/Abp.EventBus.CAP diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/README.md b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/README.md new file mode 100644 index 000000000..f6f444444 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/README.md @@ -0,0 +1,17 @@ +# LINGYUN.Abp.EventBus.CAP + +分布式事件总线 CAP 集成 + +#### 注意 + +* 由于 CAP 官方模块中, MySqlConnector 为高版本,与 Volo.Abp.EntityFrameworkCore.MySQL 依赖版本不兼容 +当 Abp 框架升级到 4.0 版本之后,此模块升级为 CAP 最新版本 + +## 配置使用 + +```csharp +[DependsOn(typeof(AbpCAPEventBusModule))] +public class YouProjectModule : AbpModule +{ + // other +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationCleanupOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationCleanupOptions.cs index 3c92996b2..2fe7b3a1f 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationCleanupOptions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationCleanupOptions.cs @@ -9,9 +9,9 @@ public bool IsEnabled { get; set; } = true; /// /// 清理时间间隔 - /// 默认:300000ms + /// 默认:30_0000ms /// - public int CleanupPeriod { get; set; } = 300000; + public int CleanupPeriod { get; set; } = 30_0000; /// /// 清理批次 /// 默认: 200 diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs index 57040f150..9bbc95eb3 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs @@ -94,7 +94,7 @@ namespace LINGYUN.Abp.Notifications Task> GetUserNotificationsAsync( Guid? tenantId, Guid userId, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int maxResultCount = 10, CancellationToken cancellationToken = default); @@ -102,7 +102,7 @@ namespace LINGYUN.Abp.Notifications Guid? tenantId, Guid userId, string filter = "", - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, CancellationToken cancellationToken = default); Task> GetUserNotificationsAsync( @@ -111,7 +111,7 @@ namespace LINGYUN.Abp.Notifications string filter = "", string sorting = nameof(NotificationInfo.CreationTime), bool reverse = true, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int skipCount = 1, int maxResultCount = 10, CancellationToken cancellationToken = default); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NullNotificationStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NullNotificationStore.cs index a954bdddc..8062548a5 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NullNotificationStore.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NullNotificationStore.cs @@ -6,9 +6,8 @@ using Volo.Abp.DependencyInjection; namespace LINGYUN.Abp.Notifications { - [Dependency(Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton, TryRegister = true)] - [ExposeServices(typeof(INotificationStore))] - public class NullNotificationStore : INotificationStore + [Dependency(TryRegister = true)] + public class NullNotificationStore : INotificationStore, ISingletonDependency { public Task ChangeUserNotificationReadStateAsync( Guid? tenantId, @@ -88,8 +87,8 @@ namespace LINGYUN.Abp.Notifications public Task> GetUserNotificationsAsync( Guid? tenantId, - Guid userId, - NotificationReadState readState = NotificationReadState.UnRead, + Guid userId, + NotificationReadState? readState = null, int maxResultCount = 10, CancellationToken cancellationToken = default) { @@ -100,7 +99,7 @@ namespace LINGYUN.Abp.Notifications Guid? tenantId, Guid userId, string filter = "", - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, CancellationToken cancellationToken = default) { return Task.FromResult(0); @@ -112,7 +111,7 @@ namespace LINGYUN.Abp.Notifications string filter = "", string sorting = nameof(NotificationInfo.CreationTime), bool reverse = true, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int skipCount = 1, int maxResultCount = 10, CancellationToken cancellationToken = default) diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/README.md b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/README.md new file mode 100644 index 000000000..df6076035 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/README.md @@ -0,0 +1,19 @@ +# LINGYUN.Abp.Notifications + +实时通知基础模块 + + +#### 注意 + +* 当前的通知数据模型 NotificationData 设计极度不合理 + + 将在框架升级为4.0版本之后变更,将与现有通知数据不兼容(这可能就是敏捷开发的避免吧 ;) ) + +## 配置使用 + +```csharp +[DependsOn(typeof(AbpNotificationModule))] +public class YouProjectModule : AbpModule +{ + // other +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/Dto/UserNotificationGetByPagedDto.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/Dto/UserNotificationGetByPagedDto.cs index b1e811463..4f4651498 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/Dto/UserNotificationGetByPagedDto.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN/Abp/MessageService/Notifications/Dto/UserNotificationGetByPagedDto.cs @@ -9,6 +9,6 @@ namespace LINGYUN.Abp.MessageService.Notifications public bool Reverse { get; set; } - public NotificationReadState ReadState { get; set; } = NotificationReadState.Read; + public NotificationReadState? ReadState { get; set; } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDomainModule.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDomainModule.cs index 2f19e44ef..53ec1d2bd 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDomainModule.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDomainModule.cs @@ -2,6 +2,9 @@ using LINGYUN.Abp.MessageService.Localization; using LINGYUN.Abp.MessageService.Mapper; using LINGYUN.Abp.MessageService.ObjectExtending; +using LINGYUN.Abp.MessageService.Utils; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; using Volo.Abp.AutoMapper; using Volo.Abp.Caching; using Volo.Abp.Localization; @@ -51,5 +54,13 @@ namespace LINGYUN.Abp.MessageService typeof(Message) ); } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + context + .ServiceProvider + .GetRequiredService() + .Initialize(); + } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs index 6942ac069..16312df09 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs @@ -25,14 +25,14 @@ namespace LINGYUN.Abp.MessageService.Notifications Task> GetNotificationsAsync( Guid userId, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int maxResultCount = 10, CancellationToken cancellationToken = default); Task GetCountAsync( Guid userId, string filter = "", - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, CancellationToken cancellationToken = default); Task> GetListAsync( @@ -40,15 +40,9 @@ namespace LINGYUN.Abp.MessageService.Notifications string filter = "", string sorting = nameof(Notification.CreationTime), bool reverse = true, - NotificationReadState readState = NotificationReadState.UnRead, - int skipCount = 1, + NotificationReadState? readState = null, + int skipCount = 0, int maxResultCount = 10, CancellationToken cancellationToken = default); - - Task ChangeUserNotificationReadStateAsync( - Guid userId, - long notificationId, - NotificationReadState readState, - CancellationToken cancellationToken = default); } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs index b3a77f5b0..c02be6207 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.MessageService.Subscriptions; using LINGYUN.Abp.MessageService.Utils; using LINGYUN.Abp.Notifications; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; @@ -15,7 +16,9 @@ using Volo.Abp.Uow; namespace LINGYUN.Abp.MessageService.Notifications { - public class NotificationStore : INotificationStore, ITransientDependency + [Dependency(ServiceLifetime.Transient, ReplaceServices = true)] + [ExposeServices(typeof(INotificationStore))] + public class NotificationStore : INotificationStore { private readonly IClock _clock; @@ -68,10 +71,14 @@ namespace LINGYUN.Abp.MessageService.Notifications using (var unitOfWork = _unitOfWorkManager.Begin()) using (_currentTenant.Change(tenantId)) { - await _userNotificationRepository - .ChangeUserNotificationReadStateAsync(userId, notificationId, readState, cancellationToken); + var notification = await _userNotificationRepository.GetByIdAsync(userId, notificationId); + if (notification != null) + { + notification.ChangeReadState(readState); + await _userNotificationRepository.UpdateAsync(notification); - await unitOfWork.SaveChangesAsync(); + await unitOfWork.SaveChangesAsync(); + } } } @@ -212,8 +219,8 @@ namespace LINGYUN.Abp.MessageService.Notifications public virtual async Task> GetUserNotificationsAsync( Guid? tenantId, - Guid userId, - NotificationReadState readState = NotificationReadState.UnRead, + Guid userId, + NotificationReadState? readState = null, int maxResultCount = 10, CancellationToken cancellationToken = default) { @@ -230,7 +237,7 @@ namespace LINGYUN.Abp.MessageService.Notifications Guid? tenantId, Guid userId, string filter = "", - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, CancellationToken cancellationToken = default) { using (_currentTenant.Change(tenantId)) @@ -246,7 +253,7 @@ namespace LINGYUN.Abp.MessageService.Notifications string filter = "", string sorting = nameof(NotificationInfo.CreationTime), bool reverse = true, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int skipCount = 1, int maxResultCount = 10, CancellationToken cancellationToken = default) diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/SnowflakeIdGenerator.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/SnowflakeIdGenerator.cs new file mode 100644 index 000000000..65a67ecc6 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/SnowflakeIdGenerator.cs @@ -0,0 +1,109 @@ +using Microsoft.Extensions.Options; +using System; +using Volo.Abp; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.MessageService.Utils +{ + // reference: https://github.com/dotnetcore/CAP + // reference: https://blog.csdn.net/lq18050010830/article/details/89845790 + public class SnowflakeIdGenerator : ISnowflakeIdGenerator, ISingletonDependency + { + public const long Twepoch = 1288834974657L; + + private static readonly object _lock = new object(); + private long _lastTimestamp = -1L; + + protected long MaxWorkerId { get; set; } + protected long MaxDatacenterId { get; set; } + + protected int WorkerIdShift { get; } + protected int DatacenterIdShift { get; } + protected int TimestampLeftShift { get; } + protected long SequenceMask { get; } + + protected SnowflakeIdOptions Options { get; } + + public SnowflakeIdGenerator(IOptions options) + { + Options = options.Value; + + WorkerIdShift = Options.SequenceBits; + DatacenterIdShift = Options.SequenceBits + Options.WorkerIdBits; + TimestampLeftShift = Options.SequenceBits + Options.WorkerIdBits + Options.DatacenterIdBits; + SequenceMask = -1L ^ (-1L << Options.SequenceBits); + } + + internal void Initialize(long sequence = 0L) + { + Sequence = sequence; + MaxWorkerId = -1L ^ (-1L << Options.WorkerIdBits); + MaxDatacenterId = -1L ^ (-1L << Options.DatacenterIdBits); + + if (!int.TryParse(Environment.GetEnvironmentVariable("WORKERID", EnvironmentVariableTarget.Machine), out var workerId)) + { + workerId = RandomHelper.GetRandom((int)MaxWorkerId); + } + + if (!int.TryParse(Environment.GetEnvironmentVariable("DATACENTERID", EnvironmentVariableTarget.Machine), out var datacenterId)) + { + datacenterId = RandomHelper.GetRandom((int)MaxDatacenterId); + } + + if (workerId > MaxWorkerId || workerId < 0) + throw new ArgumentException($"worker Id can't be greater than {MaxWorkerId} or less than 0"); + + if (datacenterId > MaxDatacenterId || datacenterId < 0) + throw new ArgumentException($"datacenter Id can't be greater than {MaxDatacenterId} or less than 0"); + + WorkerId = workerId; + DatacenterId = datacenterId; + + } + + public long WorkerId { get; protected set; } + public long DatacenterId { get; protected set; } + public long Sequence { get; protected set; } + + public virtual long Create() + { + lock (_lock) + { + var timestamp = TimeGen(); + + if (timestamp < _lastTimestamp) + throw new Exception( + $"InvalidSystemClock: Clock moved backwards, Refusing to generate id for {_lastTimestamp - timestamp} milliseconds"); + + if (_lastTimestamp == timestamp) + { + Sequence = (Sequence + 1) & SequenceMask; + if (Sequence == 0) timestamp = TilNextMillis(_lastTimestamp); + } + else + { + Sequence = 0; + } + + _lastTimestamp = timestamp; + var id = ((timestamp - Twepoch) << TimestampLeftShift) | + (DatacenterId << DatacenterIdShift) | + (WorkerId << WorkerIdShift) | Sequence; + + return id; + } + } + + protected virtual long TilNextMillis(long lastTimestamp) + { + var timestamp = TimeGen(); + while (timestamp <= lastTimestamp) timestamp = TimeGen(); + return timestamp; + } + + protected virtual long TimeGen() + { + return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/SnowflakeIdOptions.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/SnowflakeIdOptions.cs new file mode 100644 index 000000000..ac594b900 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/SnowflakeIdOptions.cs @@ -0,0 +1,24 @@ +namespace LINGYUN.Abp.MessageService.Utils +{ + public class SnowflakeIdOptions + { + /// + /// 机器Id长度 + /// + public int WorkerIdBits { get; set; } + /// + /// 机房Id长度 + /// + public int DatacenterIdBits { get; set; } + /// + /// 每秒生成Id的数量 + /// + public int SequenceBits { get; set; } + public SnowflakeIdOptions() + { + WorkerIdBits = 5; + DatacenterIdBits = 5; + SequenceBits = 12; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs index ee89175f9..2d410e561 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs @@ -39,18 +39,6 @@ namespace LINGYUN.Abp.MessageService.Notifications await DbSet.AddRangeAsync(userNotifications, GetCancellationToken(cancellationToken)); } - public virtual async Task ChangeUserNotificationReadStateAsync( - Guid userId, - long notificationId, - NotificationReadState readState, - CancellationToken cancellationToken = default) - { - var userNofitication = await GetByIdAsync(userId, notificationId, cancellationToken); - userNofitication.ChangeReadState(readState); - - DbSet.Update(userNofitication); - } - public virtual async Task GetByIdAsync( Guid userId, long notificationId, @@ -65,17 +53,20 @@ namespace LINGYUN.Abp.MessageService.Notifications public virtual async Task> GetNotificationsAsync( Guid userId, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int maxResultCount = 10, CancellationToken cancellationToken = default) { - var userNotifilerQuery = from un in DbContext.Set() - join n in DbContext.Set() + var userNotifilerQuery = DbContext.Set() + .Where(x => x.UserId == userId) + .WhereIf(readState.HasValue, x => x.ReadStatus == readState.Value); + + var notifilerQuery = from un in userNotifilerQuery + join n in DbContext.Set() on un.NotificationId equals n.NotificationId - where un.UserId.Equals(userId) && un.ReadStatus.Equals(readState) - select n; + select n; - return await userNotifilerQuery + return await notifilerQuery .OrderBy(nameof(Notification.CreationTime) + " DESC") .Take(maxResultCount) .AsNoTracking() @@ -84,17 +75,20 @@ namespace LINGYUN.Abp.MessageService.Notifications public virtual async Task GetCountAsync( Guid userId, - string filter = "", - NotificationReadState readState = NotificationReadState.UnRead, + string filter = "", + NotificationReadState? readState = null, CancellationToken cancellationToken = default) { - var userNotifilerQuery = from un in DbContext.Set() - join n in DbContext.Set() + var userNotifilerQuery = DbContext.Set() + .Where(x => x.UserId == userId) + .WhereIf(readState.HasValue, x => x.ReadStatus == readState.Value); + + var notifilerQuery = from un in userNotifilerQuery + join n in DbContext.Set() on un.NotificationId equals n.NotificationId - where un.UserId.Equals(userId) && un.ReadStatus.Equals(readState) - select n; + select n; - return await userNotifilerQuery + return await notifilerQuery .WhereIf(!filter.IsNullOrWhiteSpace(), nf => nf.NotificationName.Contains(filter) || nf.NotificationTypeName.Contains(filter)) @@ -106,7 +100,7 @@ namespace LINGYUN.Abp.MessageService.Notifications string filter = "", string sorting = nameof(Notification.CreationTime), bool reverse = true, - NotificationReadState readState = NotificationReadState.UnRead, + NotificationReadState? readState = null, int skipCount = 1, int maxResultCount = 10, CancellationToken cancellationToken = default) @@ -114,13 +108,17 @@ namespace LINGYUN.Abp.MessageService.Notifications sorting ??= nameof(Notification.CreationTime); sorting = reverse ? sorting + " DESC" : sorting; - var userNotifilerQuery = from un in DbContext.Set() - join n in DbContext.Set() + + var userNotifilerQuery = DbContext.Set() + .Where(x => x.UserId == userId) + .WhereIf(readState.HasValue, x => x.ReadStatus == readState.Value); + + var notifilerQuery = from un in userNotifilerQuery + join n in DbContext.Set() on un.NotificationId equals n.NotificationId - where un.UserId.Equals(userId) && un.ReadStatus.Equals(readState) - select n; + select n; - return await userNotifilerQuery + return await notifilerQuery .WhereIf(!filter.IsNullOrWhiteSpace(), nf => nf.NotificationName.Contains(filter) || nf.NotificationTypeName.Contains(filter)) diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs index 813ddbce0..c6f3ec8e2 100644 --- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs +++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs @@ -349,10 +349,11 @@ namespace LINGYUN.Abp.BackendAdmin // 路由 app.UseConfiguredEndpoints(); + // 调试代理连接信息用,上线后注释掉 + app.UseProxyConnectTest(); + if (context.GetEnvironment().IsDevelopment()) { - // 开发模式下调试代理连接信息用 - app.UseProxyConnectTest(); SeedData(context); } } diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Utils/SnowflakeIdGenerator.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Utils/SnowflakeIdGenerator.cs deleted file mode 100644 index 0b5d5b0c8..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Utils/SnowflakeIdGenerator.cs +++ /dev/null @@ -1,16 +0,0 @@ -using DotNetCore.CAP.Internal; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.DependencyInjection; - -namespace LINGYUN.Abp.MessageService.Utils -{ - [Dependency(ServiceLifetime.Singleton, TryRegister = true)] - [ExposeServices(typeof(ISnowflakeIdGenerator))] - public class SnowflakeIdGenerator : ISnowflakeIdGenerator - { - public long Create() - { - return SnowflakeId.Default().NextId(); - } - } -} diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN.Abp.MessageService.Domain.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN.Abp.MessageService.Domain.Tests.csproj new file mode 100644 index 000000000..cc3016aab --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN.Abp.MessageService.Domain.Tests.csproj @@ -0,0 +1,23 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN/Abp/MessageService/AbpMessageServiceDomainTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN/Abp/MessageService/AbpMessageServiceDomainTestModule.cs new file mode 100644 index 000000000..b2b7ef786 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN/Abp/MessageService/AbpMessageServiceDomainTestModule.cs @@ -0,0 +1,36 @@ +using LINGYUN.Abp.Notifications; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.MessageService +{ + [DependsOn( + typeof(AbpMessageServiceDomainModule), + typeof(AbpNotificationsTestsModule) + )] + public class AbpMessageServiceDomainTestModule : AbpModule + { + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + var dataSeeder = scope.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(async () => + { + await dataSeeder.SeedAsync(); + await scope.ServiceProvider + .GetRequiredService() + .BuildAsync(); + }); + } + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN/Abp/MessageService/AbpNotificationsTestsDataBuilder.cs b/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN/Abp/MessageService/AbpNotificationsTestsDataBuilder.cs new file mode 100644 index 000000000..72afa4cf8 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.Domain.Tests/LINGYUN/Abp/MessageService/AbpNotificationsTestsDataBuilder.cs @@ -0,0 +1,75 @@ +using LINGYUN.Abp.MessageService.Notifications; +using LINGYUN.Abp.Notifications; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.MessageService +{ + public class AbpNotificationsTestDataBuilder : ITransientDependency + { + private readonly INotificationStore _notificationStore; + private readonly IUserNotificationRepository _userNotificationRepository; + public AbpNotificationsTestDataBuilder( + INotificationStore notificationStore, + IUserNotificationRepository userNotificationRepository) + { + _notificationStore = notificationStore; + _userNotificationRepository = userNotificationRepository; + } + + public async Task BuildAsync() + { + await AddNotificationsAsync(); + } + + private async Task AddUserNotificationsAsync(NotificationInfo notificationInfo, IEnumerable userIds) + { + await _notificationStore.InsertUserNotificationsAsync(notificationInfo, userIds); + } + + private async Task AddNotificationsAsync() + { + var notification1 = new NotificationInfo + { + Name = NotificationsTestsNames.Test1, + Severity = NotificationSeverity.Success, + CreationTime = DateTime.Now, + Lifetime = NotificationLifetime.OnlyOne, + Type = NotificationType.Application + }; + + var notification2 = new NotificationInfo + { + Name = NotificationsTestsNames.Test2, + Severity = NotificationSeverity.Success, + CreationTime = DateTime.Now, + Lifetime = NotificationLifetime.Persistent, + Type = NotificationType.Application + }; + + var notification3 = new NotificationInfo + { + Name = NotificationsTestsNames.Test3, + Severity = NotificationSeverity.Success, + CreationTime = DateTime.Now, + Lifetime = NotificationLifetime.OnlyOne, + Type = NotificationType.User + }; + + await _notificationStore.InsertNotificationAsync(notification1); + await _notificationStore.InsertNotificationAsync(notification2); + await _notificationStore.InsertNotificationAsync(notification3); + + NotificationsTestConsts.NotificationId1 = notification1.GetId(); + NotificationsTestConsts.NotificationId2 = notification2.GetId(); + NotificationsTestConsts.NotificationId3 = notification3.GetId(); + + await AddUserNotificationsAsync(notification2, new Guid[] { NotificationsTestConsts.User1Id, NotificationsTestConsts.User2Id }); + await AddUserNotificationsAsync(notification3, new Guid[] { NotificationsTestConsts.User1Id }); + + await _notificationStore.ChangeUserNotificationReadStateAsync(null, NotificationsTestConsts.User1Id, NotificationsTestConsts.NotificationId3, NotificationReadState.Read); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj new file mode 100644 index 000000000..4bb28eab1 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,24 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreTestBase.cs new file mode 100644 index 000000000..8ca6e6b72 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreTestBase.cs @@ -0,0 +1,8 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.MessageService.EntityFrameworkCore +{ + public abstract class AbpMessageServiceEntityFrameworkCoreTestBase : AbpTestsBase + { + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreTestModule.cs new file mode 100644 index 000000000..d31349d63 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreTestModule.cs @@ -0,0 +1,15 @@ +using LINGYUN.Abp.EntityFrameworkCore.Tests; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.MessageService.EntityFrameworkCore +{ + [DependsOn( + typeof(AbpMessageServiceEntityFrameworkCoreModule), + typeof(AbpMessageServiceDomainTestModule), + typeof(AbpEntityFrameworkCoreTestModule) + )] + public class AbpMessageServiceEntityFrameworkCoreTestModule : AbpModule + { + + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/Notifications/UserNotificationRepositoryTests.cs b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/Notifications/UserNotificationRepositoryTests.cs new file mode 100644 index 000000000..a23447bf1 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests/LINGYUN/Abp/MessageService/Notifications/UserNotificationRepositoryTests.cs @@ -0,0 +1,81 @@ +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using LINGYUN.Abp.Notifications; +using Shouldly; +using System.Threading.Tasks; +using Xunit; + +namespace LINGYUN.Abp.MessageService.Notifications +{ + public class UserNotificationRepositoryTests : AbpMessageServiceEntityFrameworkCoreTestBase + { + private readonly IUserNotificationRepository _repository; + public UserNotificationRepositoryTests() + { + _repository = GetRequiredService(); + } + + [Fact] + public async Task AnyAsync_Test() + { + (await _repository.AnyAsync(NotificationsTestConsts.User1Id, NotificationsTestConsts.NotificationId1)).ShouldBeFalse(); + (await _repository.AnyAsync(NotificationsTestConsts.User1Id, NotificationsTestConsts.NotificationId3)).ShouldBeTrue(); + } + + [Fact] + public async Task GetByIdAsync_Test() + { + (await _repository.GetByIdAsync(NotificationsTestConsts.User1Id, NotificationsTestConsts.NotificationId2)).ShouldNotBeNull(); + (await _repository.GetByIdAsync(NotificationsTestConsts.User1Id, NotificationsTestConsts.NotificationId1)).ShouldBeNull(); + } + + [Fact] + public async Task GetNotificationsAsync_Test() + { + (await _repository.GetNotificationsAsync( + NotificationsTestConsts.User1Id, + NotificationReadState.Read)) + .Count + .ShouldBe(1); + (await _repository.GetNotificationsAsync( + NotificationsTestConsts.User1Id, + NotificationReadState.UnRead)) + .Count + .ShouldBe(1); + (await _repository.GetNotificationsAsync( + NotificationsTestConsts.User1Id)) + .Count + .ShouldBe(2); + (await _repository.GetNotificationsAsync( + NotificationsTestConsts.User2Id, + NotificationReadState.UnRead)) + .Count + .ShouldBe(1); + } + + [Fact] + public async Task GetCountAsync_Test() + { + (await _repository.GetCountAsync( + NotificationsTestConsts.User1Id, + readState: NotificationReadState.Read)) + .ShouldBe(1); + (await _repository.GetCountAsync( + NotificationsTestConsts.User1Id)) + .ShouldBe(2); + } + + [Fact] + public async Task GetListAsync_Test() + { + (await _repository.GetListAsync( + NotificationsTestConsts.User1Id, + readState: NotificationReadState.Read)) + .Count + .ShouldBe(1); + (await _repository.GetListAsync( + NotificationsTestConsts.User1Id)) + .Count + .ShouldBe(2); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/AbpNotificationsTestsModule.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/AbpNotificationsTestsModule.cs index 74eec8126..4e8bab37b 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/AbpNotificationsTestsModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/AbpNotificationsTestsModule.cs @@ -8,6 +8,5 @@ namespace LINGYUN.Abp.Notifications typeof(AbpTestsBaseModule))] public class AbpNotificationsTestsModule : AbpModule { - } } diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestConsts.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestConsts.cs new file mode 100644 index 000000000..beb71a255 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestConsts.cs @@ -0,0 +1,15 @@ +using System; + +namespace LINGYUN.Abp.Notifications +{ + public static class NotificationsTestConsts + { + public static Guid User1Id { get; } = Guid.NewGuid(); + + public static Guid User2Id { get; } = Guid.NewGuid(); + + public static long NotificationId1 { get; set; } + public static long NotificationId2 { get; set; } + public static long NotificationId3 { get; set; } + } +}