From 1a29a10d8d57d7eaac15fc2b175f41e31876f1b6 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Wed, 4 Aug 2021 12:58:54 +0800 Subject: [PATCH 1/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c3d307e..5188ee27 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ [请点击链接,查看详细介绍](https://github.com/AlphaYu/Adnc/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E8%B7%91%E8%B5%B7%E6%9D%A5) #### 如何手动部署到服务器 -- 详细介绍如何使用docker安装consul集群、使用consul注册中心、安装配置Skywalking,以及相关项目dockerfile文件编写和配置等。
+- 详细介绍如何使用docker安装配置consul集群、Skywalking系列组件、相关项目的dockerfile文件编写与配置以及如何将多个服务部署到服务器。
[请点击链接,查看详细介绍](https://github.com/AlphaYu/Adnc/wiki/Adnc%E5%A6%82%E4%BD%95%E6%89%8B%E5%8A%A8%E9%83%A8%E7%BD%B2(docker,consul,skywalking,nginx)) -- Gitee From 0763dc1cc2d33cb22cd939afe4fdf2c35228d6c6 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Wed, 4 Aug 2021 13:23:09 +0800 Subject: [PATCH 2/9] Update README.md --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 5188ee27..a1a4ec5c 100644 --- a/README.md +++ b/README.md @@ -135,55 +135,55 @@ ![.NET微服务开源框架-整体架构图](https://aspdotnetcore.net/adnc_solution) #### Infrastructures 基础架构相关工程 -##### Adnc.Infra.Core +##### :white_check_mark: Adnc.Infra.Core 该工程是Adnc所有工程的最顶层,任何工程都会者直接或间接依赖该层。该工程提供了大量的`C#`基础类型的扩展方法以及Configuration、DependencyInjection、ContainerBuilder的扩展方法,还定义了一些异常类。 -##### Adnc.Infra.Caching +##### :white_check_mark: Adnc.Infra.Caching 该工程集成了StackExchange.Redis,提供缓存的管理、Redis常用类型操作、分布式锁、布隆过滤器功能。 -##### Adnc.Infra.Consul +##### :white_check_mark: Adnc.Infra.Consul 该工程集成了Consul,提供服务的自动注册、发现以及系统配置读写操作。 -##### Adnc.Infra.EfCore.MySQL +##### :white_check_mark: Adnc.Infra.EfCore.MySQL 该工程负责Adnc.Infra.Repository仓储接口以及IUintofWork接口的EfCore的实现,提供mysql数据库的CURD操作,同时也集成了Dapper部分接口,用来处理复杂查询。 -##### Adnc.Infra.EventBus +##### :white_check_mark: Adnc.Infra.EventBus 该工程简单封装了CAP,同时集成了RabbitMq,封装了发布者与订阅者等公共类,方便更加便捷的调用Rabbitmq。 -##### Adnc.Infra.Gateway +##### :white_check_mark: Adnc.Infra.Gateway 该工程是一个Web项目,基于Ocelot实现的Api网关,如果项目采用整体结构开发,该项目可以直接删除。ocelot网关包含路由、服务聚合、服务发现、认证、鉴权、限流、熔断、缓存、Header头传递等功能。市面上主流网关还有Kong,Traefik,Ambassador,Tyk等。 -##### Adnc.Infra.HealthCheckUI +##### :white_check_mark: Adnc.Infra.HealthCheckUI 该工程是一个Web项目, AspNetCore.HealthChecks组件的Dashboard,直接配置需要监测的服务地址就可以了,没有代码,关键的代码参考webapi层的AddHealthChecks()方法。 -##### Adnc.Infra.Helper +##### :white_check_mark: Adnc.Infra.Helper 该工程提供一些通用帮助类,如IdGeneraterHelper,HashHelper,SecurityHelper等等。 -##### Adnc.Infra.Mongo +##### :white_check_mark: Adnc.Infra.Mongo 该工程负责Adnc.Infra.Repository仓储接口的Mongodb实现,提供mongodb数据库的CURD操作。 -##### Adnc.Infra.Mapper +##### :white_check_mark: Adnc.Infra.Mapper 该工程定义了IObjectMapper接口,并且提供了AutoMapper的实现。 -##### Adnc.Infra.Repository +##### :white_check_mark: Adnc.Infra.Repository 该工程定义了Entity对象的基类、UnitOfWork接口、仓储接口。 #### Services 微服务相关工程 该目录都是具体微服务业务的实现。 -##### Shared +##### :white_check_mark: Shared 微服务公用工程 - `Adnc.Shared` 该层目前有三个目录Consts存放常量定义文件、Events存放事件定义文件、RPCServices存放RPC服务接口声明文件,任何层都可以依赖该层。 - `Adnc.Application.Shared` 该层定义了DTO对象的基类、应用服务类基类、缓存相关服务基类以及操作日志拦截器、UnitOfWork拦截器。所有微服务Application/Application.Contracts层的共享层,并且都需要依赖该层。 - `Adnc.WebApi.Shared` 该层实现了认证、鉴权、异常捕获、服务组件注册等公共类和中间件。所有微服务WebApi层的共享层,并且都需要依赖该层。 -##### Adnc.Usr +##### :white_check_mark: Adnc.Usr 用户中心微服务,系统支撑服务,实现了用户管理、角色管理、权限管理、菜单管理、组织架构管理。 -##### Adnc.Maint +##### :white_check_mark: Adnc.Maint 运维中心微服务,系统支撑服务,实现了登录日志、审计日志、异常日志、字典管理、配置参数管理。 -##### Adnc.Cus +##### :white_check_mark: Adnc.Cus 客户中心微服务,经典三层开发模式demo。 -##### Adnc.Ord +##### :white_check_mark: Adnc.Ord 订单中心微服务,DDD开发模式demo。 -##### Adnc.Whse +##### :white_check_mark: Adnc.Whse 仓储中心微服务,DDD开发模式demo。 > 每个微服务的Migrations层是Efcore用来做数据迁移的,迁移的日志文件存放在各自Migrations目录中。 -- Gitee From 80269e1652b01d39da5adb86e0808ba894bb7472 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Thu, 5 Aug 2021 13:14:43 +0800 Subject: [PATCH 3/9] Update README.md --- README.md | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a1a4ec5c..0a3e500a 100644 --- a/README.md +++ b/README.md @@ -190,41 +190,40 @@ ### 代码片段 ```csharp - [Route("usr/session")] - [ApiController] - public class AccountController : ControllerBase +namespace Adnc.Usr.WebApi +{ + public class Startup { - private readonly JWTConfig _jwtConfig; - private readonly IAccountAppService _accountService; - private readonly ILogger _logger; + private readonly IHostEnvironment _environment; + private IServiceCollection _services; - public AccountController(IOptionsSnapshot jwtConfig - , IAccountAppService accountService - , ILogger logger) + public Startup(IHostEnvironment environment) { - _jwtConfig = jwtConfig.Value; - _accountService = accountService; - _logger = logger; + _environment = environment; } - /// - /// 登录/验证 - /// - /// - /// - [AllowAnonymous] - [HttpPost()] - public async Task Login([FromBody]UserValidateInputDto userDto) + public void ConfigureServices(IServiceCollection services) { - var userValidateDto = await _accountService.Login(userDto); + _services = services; + services.AddAdncServices(); + } + + public void ConfigureContainer(ContainerBuilder builder) + { + builder.RegisterAdncModules(_services); + } + + public void Configure(IApplicationBuilder app) + { + app.UseAdncMiddlewares(); - return new UserTokenInfoDto + if (_environment.IsProduction() || _environment.IsStaging()) { - Token = JwtTokenHelper.CreateAccessToken(_jwtConfig, userValidateDto), - RefreshToken = JwtTokenHelper.CreateRefreshToken(_jwtConfig, userValidateDto) - }; + app.RegisterToConsul(); + } } } +} ``` ## 问题交流 -- Gitee From e7ec8854ae3023ca6c0dbe43df5080462a2b543e Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Tue, 12 Oct 2021 21:48:58 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20JetBrains.Annotations?= =?UTF-8?q?=20=E5=BC=95=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Adnc.Infra.Core/Adnc.Infra.Core.csproj | 1 - .../Adnc/Exceptions/Checker.cs | 35 ++++------ .../Extensions/Byte/ByteArrayExtension.cs | 2 +- .../Extensions/Collection/ArrayExtension.cs | 4 +- .../Collection/CollectionExtension.cs | 2 +- .../Extensions/Delegate/DelegateExtension.cs | 2 +- .../System/Extensions/Enum/EnumExtension.cs | 2 +- .../EventHandler/EventHandlerExtension.cs | 12 ++-- .../Expression/ExpressionExtension.cs | 2 +- .../System/Extensions/Guid/GuidExtension.cs | 2 +- .../Extensions/Object/ObjectArrayExtension.cs | 2 +- .../Extensions/Object/ObjectExtension.cs | 68 ++++++------------- .../Extensions/Random/RandomExtension.cs | 4 +- .../Extensions/String/StringExtension.cs | 8 +-- .../StringBuilder/StringBuilderExtension.cs | 2 +- .../System/Extensions/Type/TypeExtension.cs | 7 +- .../Adnc.Infra.EfCore.MySQL/AdncDbContext.cs | 14 ++-- .../Extensions/DbContextExtension.cs | 2 +- .../Extensions/EntityEntryExtension.cs | 1 + .../AdncMySqlQuerySqlGeneratorFactory.cs | 4 +- .../Adnc.Infra.EfCore.MySQL/PagedModel.cs | 1 - .../AdncInfraEventBusModule.cs | 23 +++++-- .../Adnc.Infra.EventBus/Cap/CapPublisher.cs | 20 ++---- .../Adnc.Infra.EventBus/Cap/CapSubscriber.cs | 4 +- .../Cap/NullCapPublisher.cs | 10 ++- .../RabbitMq/BaseRabbitMqConsumer.cs | 2 +- .../Adnc.Infra.Mongo/PagedModel.cs | 2 - .../Extentions/IQueryableExtentions.cs | 2 +- .../Extentions/Internal/Check.cs | 17 ++--- .../Dtos/Dict/DictDto.cs | 2 - .../Controllers/DeptController.cs | 1 - .../AdncApplicationModule.cs | 6 +- .../Dtos/PageModelDto.cs | 1 - .../Services/AbstractAppService.cs | 2 +- .../Services/AppServiceResult.cs | 4 +- .../Consts/CachingConsts/CachingConsts.Com.cs | 2 + .../Adnc.Shared/RpcServices/Rtos/DictRto.cs | 4 +- src/ServerApi/build/version.props | 2 +- 38 files changed, 112 insertions(+), 169 deletions(-) diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc.Infra.Core.csproj b/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc.Infra.Core.csproj index b5d19ff7..4b8ecb22 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc.Infra.Core.csproj +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc.Infra.Core.csproj @@ -5,7 +5,6 @@ - diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc/Exceptions/Checker.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc/Exceptions/Checker.cs index e8d5026d..1ba0965b 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc/Exceptions/Checker.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/Adnc/Exceptions/Checker.cs @@ -1,14 +1,14 @@ -using JetBrains.Annotations; -using System; +using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Adnc.Infra.Core { public static class Checker { public static decimal GTZero(decimal value - , [InvokerParameterName][NotNull] string parameterName) + , [NotNull] string parameterName) { if (value <= 0) throw new AdncArgumentException("不能小于0", parameterName); @@ -16,7 +16,7 @@ namespace Adnc.Infra.Core } public static int GTZero(int value - , [InvokerParameterName][NotNull] string parameterName) + , [NotNull] string parameterName) { if (value <= 0) throw new AdncArgumentException("不能小于0", parameterName); @@ -24,7 +24,7 @@ namespace Adnc.Infra.Core } public static long GTZero(long value - , [InvokerParameterName][NotNull] string parameterName) + , [NotNull] string parameterName) { if (value <= 0) throw new AdncArgumentException("不能小于0", parameterName); @@ -33,7 +33,7 @@ namespace Adnc.Infra.Core public static T NotEmptyCollection( T value, - [InvokerParameterName][NotNull] string parameterName) + [NotNull] string parameterName) { if (value == null) { @@ -48,10 +48,9 @@ namespace Adnc.Infra.Core return value; } - [ContractAnnotation("value:null => halt")] public static T NotNull( T value, - [InvokerParameterName][NotNull] string parameterName) + [NotNull] string parameterName) { if (value == null) { @@ -61,10 +60,9 @@ namespace Adnc.Infra.Core return value; } - [ContractAnnotation("value:null => halt")] public static T NotNull( T value, - [InvokerParameterName][NotNull] string parameterName, + [NotNull] string parameterName, string message) { if (value == null) @@ -74,11 +72,9 @@ namespace Adnc.Infra.Core return value; } - - [ContractAnnotation("value:null => halt")] public static string NotNull( string value, - [InvokerParameterName][NotNull] string parameterName, + [NotNull] string parameterName, int maxLength = int.MaxValue, int minLength = 0) { @@ -100,10 +96,9 @@ namespace Adnc.Infra.Core return value; } - [ContractAnnotation("value:null => halt")] public static string NotNullOrWhiteSpace( string value, - [InvokerParameterName][NotNull] string parameterName, + [NotNull] string parameterName, int maxLength = int.MaxValue, int minLength = 0) { @@ -125,10 +120,9 @@ namespace Adnc.Infra.Core return value; } - [ContractAnnotation("value:null => halt")] public static string NotNullOrEmpty( string value, - [InvokerParameterName][NotNull] string parameterName, + [NotNull] string parameterName, int maxLength = int.MaxValue, int minLength = 0) { @@ -150,8 +144,7 @@ namespace Adnc.Infra.Core return value; } - [ContractAnnotation("value:null => halt")] - public static ICollection NotNullOrEmpty(ICollection value, [InvokerParameterName][NotNull] string parameterName) + public static ICollection NotNullOrEmpty(ICollection value, [NotNull] string parameterName) { if (value.IsNullOrEmpty()) { @@ -162,8 +155,8 @@ namespace Adnc.Infra.Core } public static string Length( - [CanBeNull] string value, - [InvokerParameterName][NotNull] string parameterName, + string value, + [NotNull] string parameterName, int maxLength, int minLength = 0) { diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Byte/ByteArrayExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Byte/ByteArrayExtension.cs index 5d1a0d83..56a5530f 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Byte/ByteArrayExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Byte/ByteArrayExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/ArrayExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/ArrayExtension.cs index 2c5fab83..11f14793 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/ArrayExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/ArrayExtension.cs @@ -1,5 +1,5 @@ -using JetBrains.Annotations; -using System.Collections; +using System.Collections; +using System.Diagnostics.CodeAnalysis; namespace System { diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/CollectionExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/CollectionExtension.cs index a1ab458a..f1c9ba15 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/CollectionExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Collection/CollectionExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Text; diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Delegate/DelegateExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Delegate/DelegateExtension.cs index 3ddc2d71..40971ed2 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Delegate/DelegateExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Delegate/DelegateExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; namespace System { diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Enum/EnumExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Enum/EnumExtension.cs index b7ef7a8f..244e63b2 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Enum/EnumExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Enum/EnumExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.ComponentModel; using System.Reflection; diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/EventHandler/EventHandlerExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/EventHandler/EventHandlerExtension.cs index 3e0770af..0d5ee791 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/EventHandler/EventHandlerExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/EventHandler/EventHandlerExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; namespace System { @@ -9,9 +9,9 @@ namespace System /// /// The @this to act on. /// Source of the event. - public static void RaiseEvent([CanBeNull] this EventHandler @this, object sender) + public static void RaiseEvent([MaybeNull] this EventHandler @this, object sender) { - @this?.Invoke(sender, null); + @this?.Invoke(sender, EventArgs.Empty); } /// @@ -20,7 +20,7 @@ namespace System /// The handler to act on. /// Source of the event. /// Event information. - public static void RaiseEvent([CanBeNull] this EventHandler handler, object sender, EventArgs e) + public static void RaiseEvent([MaybeNull] this EventHandler handler, object sender, EventArgs e) { handler?.Invoke(sender, e); } @@ -31,7 +31,7 @@ namespace System /// Type of the event arguments. /// The @this to act on. /// Source of the event. - public static void RaiseEvent([CanBeNull] this EventHandler @this, object sender) where TEventArgs : EventArgs + public static void RaiseEvent([MaybeNull] this EventHandler @this, object sender) where TEventArgs : EventArgs { @this?.Invoke(sender, Activator.CreateInstance()); } @@ -43,7 +43,7 @@ namespace System /// The @this to act on. /// Source of the event. /// Event information to send to registered event handlers. - public static void RaiseEvent([CanBeNull] this EventHandler @this, object sender, TEventArgs e) where TEventArgs : EventArgs + public static void RaiseEvent([MaybeNull] this EventHandler @this, object sender, TEventArgs e) where TEventArgs : EventArgs { @this?.Invoke(sender, e); } diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Expression/ExpressionExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Expression/ExpressionExtension.cs index bc637bb7..6ce5d513 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Expression/ExpressionExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Expression/ExpressionExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Linq.Expressions diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Guid/GuidExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Guid/GuidExtension.cs index 736ffbee..47c1ee5d 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Guid/GuidExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Guid/GuidExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; namespace System { diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectArrayExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectArrayExtension.cs index e19c1c8a..01741f61 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectArrayExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectArrayExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; namespace System { diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectExtension.cs index da7ae29d..0c411352 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Object/ObjectExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.ComponentModel; using System.IO; using System.Runtime.Serialization; @@ -22,7 +22,7 @@ namespace System } catch (Exception) { - return default(T); + return default; } } @@ -103,22 +103,12 @@ namespace System return (T)@this; } var converter = TypeDescriptor.GetConverter(@this); - if (converter != null) - { - if (converter.CanConvertTo(targetType)) - { - return (T)converter.ConvertTo(@this, targetType); - } - } + if (converter != null && converter.CanConvertTo(targetType)) + return (T)converter.ConvertTo(@this, targetType); converter = TypeDescriptor.GetConverter(targetType); - if (converter != null) - { - if (converter.CanConvertFrom(@this.GetType())) - { - return (T)converter.ConvertFrom(@this); - } - } + if (converter != null&& converter.CanConvertFrom(@this.GetType())) + return (T)converter.ConvertFrom(@this); if (@this == DBNull.Value) { @@ -134,7 +124,7 @@ namespace System /// this. /// The type. /// An object. - public static object To([CanBeNull] this object @this, Type type) + public static object To([MaybeNull] this object @this, Type type) { if (@this != null) { @@ -146,27 +136,15 @@ namespace System } var converter = TypeDescriptor.GetConverter(@this); - if (converter != null) - { - if (converter.CanConvertTo(targetType)) - { - return converter.ConvertTo(@this, targetType); - } - } + if (converter != null&& converter.CanConvertTo(targetType)) + return converter.ConvertTo(@this, targetType); converter = TypeDescriptor.GetConverter(targetType); - if (converter != null) - { - if (converter.CanConvertFrom(@this.GetType())) - { - return converter.ConvertFrom(@this); - } - } + if (converter != null&& converter.CanConvertFrom(@this.GetType())) + return converter.ConvertFrom(@this); if (@this == DBNull.Value) - { return null; - } return Convert.ChangeType(@this, targetType); } @@ -181,7 +159,7 @@ namespace System /// this. /// The default value factory. /// The given data converted to a T. - public static T ToOrDefault([CanBeNull] this object @this, Func defaultValueFactory) + public static T ToOrDefault([MaybeNull] this object @this, Func defaultValueFactory) { try { @@ -229,7 +207,7 @@ namespace System /// Generic type parameter. /// this. /// The given data converted to a T. - public static T ToOrDefault([CanBeNull] this object @this) + public static T ToOrDefault([MaybeNull] this object @this) { return @this.ToOrDefault(x => default(T)); } @@ -241,7 +219,7 @@ namespace System /// this. /// The default value. /// The given data converted to a T. - public static T ToOrDefault([CanBeNull] this object @this, T defaultValue) + public static T ToOrDefault([MaybeNull] this object @this, T defaultValue) { return @this.ToOrDefault(x => defaultValue); } @@ -292,14 +270,12 @@ namespace System /// the copied object. public static T DeepClone([NotNull] this T @this) { - using (var stream = new MemoryStream()) - { - IFormatter formatter = new BinaryFormatter(); - formatter.Serialize(stream, @this); - formatter.Context = new StreamingContext(StreamingContextStates.Clone); - stream.Seek(0, SeekOrigin.Begin); - return (T)formatter.Deserialize(stream); - } + using var stream = new MemoryStream(); + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(stream, @this); + formatter.Context = new StreamingContext(StreamingContextStates.Clone); + stream.Seek(0, SeekOrigin.Begin); + return (T)formatter.Deserialize(stream); } /// @@ -334,7 +310,7 @@ namespace System } catch (Exception) { - return default(TResult); + return default; } } @@ -413,7 +389,7 @@ namespace System } catch { - result = default(TResult); + result = default; return false; } } diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Random/RandomExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Random/RandomExtension.cs index 6c720181..22176dd5 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Random/RandomExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Random/RandomExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics; namespace System @@ -11,7 +11,7 @@ namespace System /// /// /// - public static int StrictNext(this Random r, int seed = int.MaxValue) + public static int StrictNext(this Random _, int seed = int.MaxValue) { return new Random((int)Stopwatch.GetTimestamp()).Next(seed); } diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/String/StringExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/String/StringExtension.cs index a32dc57a..76938b09 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/String/StringExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/String/StringExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -213,7 +213,7 @@ namespace System { return string.Empty; } - return @this.Substring(startIndex); + return @this[startIndex..]; } /// @@ -248,7 +248,7 @@ namespace System { return string.Empty; } - return @this.Substring(@this.Length + startIndex); + return @this[(@this.Length + startIndex)..]; } /// @@ -389,8 +389,6 @@ namespace System { bool status = long.TryParse(@this, out long result); - //return status ? result : null; - if (status) return result; else diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/StringBuilder/StringBuilderExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/StringBuilder/StringBuilderExtension.cs index 6b570dad..5f7062fd 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/StringBuilder/StringBuilderExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/StringBuilder/StringBuilderExtension.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; namespace System.Text diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Type/TypeExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Type/TypeExtension.cs index 9ee83e59..e24c4e48 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Type/TypeExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/System/Extensions/Type/TypeExtension.cs @@ -1,6 +1,5 @@ using Adnc.Infra.Core.Internal; -using JetBrains.Annotations; -using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -395,7 +394,6 @@ namespace System property?.GetValueSetter()?.Invoke(@this, value); } - [CanBeNull] public static Func GetValueGetter([NotNull] this PropertyInfo @this) { return StrongTypedDictionary.PropertyValueGetters.GetOrAdd(@this, prop => @@ -410,7 +408,6 @@ namespace System }); } - [CanBeNull] public static Func GetValueGetter([NotNull] this PropertyInfo @this) { return ReflectionDictionary.PropertyValueGetters.GetOrAdd(@this, prop => @@ -429,7 +426,6 @@ namespace System }); } - [CanBeNull] public static Action GetValueSetter([NotNull] this PropertyInfo @this) { return ReflectionDictionary.PropertyValueSetters.GetOrAdd(@this, prop => @@ -456,7 +452,6 @@ namespace System }); } - [CanBeNull] public static Action GetValueSetter([NotNull] this PropertyInfo @this) where T : class { return StrongTypedDictionary.PropertyValueSetters.GetOrAdd(@this, prop => diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/AdncDbContext.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/AdncDbContext.cs index 32d2b15c..11e0c77c 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/AdncDbContext.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/AdncDbContext.cs @@ -1,8 +1,8 @@ using Adnc.Infra.Entities; using Adnc.Infra.IRepositories; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -58,20 +58,16 @@ namespace Adnc.Infra.EfCore.MySQL foreach (var entry in allBasicAuditEntities) { var entity = entry.Entity; - { - entity.CreateBy = _operater.Id; - entity.CreateTime = DateTime.Now; - } + entity.CreateBy = _operater.Id; + entity.CreateTime = DateTime.Now; } var auditFullEntities = ChangeTracker.Entries().Where(x => x.State == EntityState.Modified); foreach (var entry in auditFullEntities) { var entity = entry.Entity; - { - entity.ModifyBy = _operater.Id; - entity.ModifyTime = DateTime.Now; - } + entity.ModifyBy = _operater.Id; + entity.ModifyTime = DateTime.Now; } return allEntities.Count(); diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/DbContextExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/DbContextExtension.cs index 5a4e3cb1..1ab94b7c 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/DbContextExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/DbContextExtension.cs @@ -1,8 +1,8 @@ using Adnc.Infra.EfCore.Internal; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Microsoft.EntityFrameworkCore diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/EntityEntryExtension.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/EntityEntryExtension.cs index ce730485..f8fed7d5 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/EntityEntryExtension.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Extensions/EntityEntryExtension.cs @@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Metadata; using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Microsoft.EntityFrameworkCore.ChangeTracking diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Internal/AdncMySqlQuerySqlGeneratorFactory.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Internal/AdncMySqlQuerySqlGeneratorFactory.cs index 97393350..81f07f47 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Internal/AdncMySqlQuerySqlGeneratorFactory.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/Internal/AdncMySqlQuerySqlGeneratorFactory.cs @@ -1,11 +1,11 @@ using Adnc.Infra.EfCore; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal; using Pomelo.EntityFrameworkCore.MySql.Query.Internal; using System; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; namespace Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal @@ -56,7 +56,7 @@ namespace Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal public AdncQuerySqlGenerator( [NotNull] QuerySqlGeneratorDependencies dependencies, [NotNull] MySqlSqlExpressionFactory sqlExpressionFactory, - [CanBeNull] IMySqlOptions options) : base(dependencies, sqlExpressionFactory, options) + [MaybeNull] IMySqlOptions options) : base(dependencies, sqlExpressionFactory, options) { ContextId = Guid.NewGuid(); } diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/PagedModel.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/PagedModel.cs index 8876d4c7..821f8799 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/PagedModel.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EfCore.MySQL/PagedModel.cs @@ -16,7 +16,6 @@ namespace Adnc.Infra.EfCore private IReadOnlyList _data = Array.Empty(); - [NotNull] public IReadOnlyList Data { get => _data; diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/AdncInfraEventBusModule.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/AdncInfraEventBusModule.cs index ce632dae..58606cd8 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/AdncInfraEventBusModule.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/AdncInfraEventBusModule.cs @@ -2,6 +2,8 @@ using Adnc.Infra.EventBus.Cap; using Adnc.Infra.EventBus.RabbitMq; using Autofac; +using DotNetCore.CAP; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Collections.Generic; using System.Linq; @@ -14,11 +16,10 @@ namespace Adnc.Infra.Mq private readonly IEnumerable _assembliesToScan; public AdncInfraEventBusModule(IEnumerable assembliesToScan) - { - _assembliesToScan = assembliesToScan; - } + => _assembliesToScan = assembliesToScan; - public AdncInfraEventBusModule(params Assembly[] assembliesToScan) : this((IEnumerable)assembliesToScan) + public AdncInfraEventBusModule(params Assembly[] assembliesToScan) + : this((IEnumerable)assembliesToScan) { } @@ -33,12 +34,20 @@ namespace Adnc.Infra.Mq //注册Rabbitmq消费者 builder.RegisterAssemblyTypes(_assembliesToScan.ToArray()) - .Where(t => t.IsAssignableTo() && t.IsAssignableTo() && !t.IsAbstract) - .AsImplementedInterfaces() - .SingleInstance(); + .Where(t => t.IsAssignableTo() && t.IsAssignableTo() && !t.IsAbstract) + .AsImplementedInterfaces() + .SingleInstance(); //注册事件发布者 builder.RegisterType().As().SingleInstance(); } + + protected virtual void Load(IServiceCollection service) + { + var implements = _assembliesToScan.SelectMany(x=>x.GetTypes()) + .Where(imp => typeof(ICapSubscribe).IsAssignableFrom(imp) && !imp.IsAbstract) + .ToList(); + implements.ForEach(loader => service.AddSingleton(loader)); + } } } \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapPublisher.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapPublisher.cs index c5307fa6..3ebd24b7 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapPublisher.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapPublisher.cs @@ -10,32 +10,22 @@ namespace Adnc.Infra.EventBus.Cap private readonly ICapPublisher _eventBus; public CapPublisher(ICapPublisher capPublisher) - { - _eventBus = capPublisher; - } + => _eventBus = capPublisher; public virtual async Task PublishAsync(T eventObj, string callbackName = null, CancellationToken cancellationToken = default) where T : IEvent - { - await _eventBus.PublishAsync(typeof(T).Name, eventObj, callbackName, cancellationToken); - } + => await _eventBus.PublishAsync(typeof(T).Name, eventObj, callbackName, cancellationToken); public virtual async Task PublishAsync(T eventObj, IDictionary headers, CancellationToken cancellationToken = default) where T : IEvent - { - await _eventBus.PublishAsync(typeof(T).Name, eventObj, headers, cancellationToken); - } + => await _eventBus.PublishAsync(typeof(T).Name, eventObj, headers, cancellationToken); public virtual void Publish(T eventObj, string callbackName = null) where T : IEvent - { - _eventBus.Publish(typeof(T).Name, eventObj, callbackName); - } + => _eventBus.Publish(typeof(T).Name, eventObj, callbackName); public virtual void Publish(T eventObj, IDictionary headers) where T : IEvent - { - _eventBus.Publish(typeof(T).Name, eventObj, headers); - } + => _eventBus.Publish(typeof(T).Name, eventObj, headers); } } \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapSubscriber.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapSubscriber.cs index 37c61180..6814fc3e 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapSubscriber.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/CapSubscriber.cs @@ -7,8 +7,6 @@ namespace Adnc.Infra.EventBus.Cap public abstract class CapSubscriber : IEventSubscriber, ICapSubscribe { protected Expression>[] UpdatingProps(params Expression>[] expressions) - { - return expressions; - } + => expressions; } } \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/NullCapPublisher.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/NullCapPublisher.cs index 41f78433..c79d815f 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/NullCapPublisher.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/Cap/NullCapPublisher.cs @@ -17,20 +17,18 @@ namespace Adnc.Infra.EventBus.Cap public void Publish(string name, T contentObj, string callbackName = null) { + // Method intentionally left empty. } public void Publish(string name, T contentObj, IDictionary headers) { + // Method intentionally left empty. } public Task PublishAsync(string name, T contentObj, string callbackName = null, CancellationToken cancellationToken = default) - { - return Task.CompletedTask; - } + => Task.CompletedTask; public Task PublishAsync(string name, T contentObj, IDictionary headers, CancellationToken cancellationToken = default) - { - return Task.CompletedTask; - } + => Task.CompletedTask; } } \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/RabbitMq/BaseRabbitMqConsumer.cs b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/RabbitMq/BaseRabbitMqConsumer.cs index b06e4e9c..d4c2a599 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/RabbitMq/BaseRabbitMqConsumer.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.EventBus/RabbitMq/BaseRabbitMqConsumer.cs @@ -15,7 +15,7 @@ namespace Adnc.Infra.EventBus.RabbitMq private readonly IModel _channel; private readonly ILogger _logger; - public BaseRabbitMqConsumer(IOptionsMonitor options, ILogger logger) + protected BaseRabbitMqConsumer(IOptionsMonitor options, ILogger logger) { _connection = RabbitMqConnection.GetInstance(options, logger).Connection; _channel = _connection.CreateModel(); diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Mongo/PagedModel.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Mongo/PagedModel.cs index b73a955a..652f39d2 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Mongo/PagedModel.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Mongo/PagedModel.cs @@ -1,5 +1,4 @@ using Adnc.Infra.IRepositories; -using JetBrains.Annotations; using System; using System.Collections.Generic; @@ -16,7 +15,6 @@ namespace Adnc.Infra.Mongo private IReadOnlyList _data = Array.Empty(); - [NotNull] public IReadOnlyList Data { get => _data; diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs index 1e375aad..0de7fce5 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs @@ -1,11 +1,11 @@ using Adnc.Infra.Repository.IRepositories.Extentions.Internal; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/Internal/Check.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/Internal/Check.cs index 60889048..c7f99980 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/Internal/Check.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/Internal/Check.cs @@ -1,8 +1,8 @@ -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Diagnostics; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Adnc.Infra.Repository.IRepositories.Extentions.Internal @@ -10,8 +10,7 @@ namespace Adnc.Infra.Repository.IRepositories.Extentions.Internal [DebuggerStepThrough] internal static class Check { - [ContractAnnotation("value:null => halt")] - public static T NotNull([NoEnumeration] T value, [InvokerParameterName][NotNull] string parameterName) + public static T NotNull( T value, [NotNull] string parameterName) { #pragma warning disable IDE0041 // Use 'is null' check if (ReferenceEquals(value, null)) @@ -25,8 +24,7 @@ namespace Adnc.Infra.Repository.IRepositories.Extentions.Internal return value; } - [ContractAnnotation("value:null => halt")] - public static IReadOnlyList NotEmpty(IReadOnlyList value, [InvokerParameterName][NotNull] string parameterName) + public static IReadOnlyList NotEmpty(IReadOnlyList value, [NotNull] string parameterName) { NotNull(value, parameterName); @@ -40,8 +38,7 @@ namespace Adnc.Infra.Repository.IRepositories.Extentions.Internal return value; } - [ContractAnnotation("value:null => halt")] - public static string NotEmpty(string value, [InvokerParameterName][NotNull] string parameterName) + public static string NotEmpty(string value, [NotNull] string parameterName) { Exception e = null; if (value is null) @@ -63,7 +60,7 @@ namespace Adnc.Infra.Repository.IRepositories.Extentions.Internal return value; } - public static string NullButNotEmpty(string value, [InvokerParameterName][NotNull] string parameterName) + public static string NullButNotEmpty(string value, [NotNull] string parameterName) { if (!(value is null) && value.Length == 0) @@ -76,7 +73,7 @@ namespace Adnc.Infra.Repository.IRepositories.Extentions.Internal return value; } - public static IReadOnlyList HasNoNulls(IReadOnlyList value, [InvokerParameterName][NotNull] string parameterName) + public static IReadOnlyList HasNoNulls(IReadOnlyList value, [NotNull] string parameterName) where T : class { NotNull(value, parameterName); diff --git a/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.Application.Contracts/Dtos/Dict/DictDto.cs b/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.Application.Contracts/Dtos/Dict/DictDto.cs index 669b80c5..c2634fc9 100644 --- a/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.Application.Contracts/Dtos/Dict/DictDto.cs +++ b/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.Application.Contracts/Dtos/Dict/DictDto.cs @@ -1,5 +1,4 @@ using Adnc.Application.Shared.Dtos; -using JetBrains.Annotations; using System; using System.Collections.Generic; @@ -18,7 +17,6 @@ namespace Adnc.Maint.Application.Contracts.Dtos private IList _data = Array.Empty(); - [NotNull] public IList Children { get => _data; diff --git a/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/Controllers/DeptController.cs b/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/Controllers/DeptController.cs index 304682d5..eab805de 100644 --- a/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/Controllers/DeptController.cs +++ b/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/Controllers/DeptController.cs @@ -1,7 +1,6 @@ using Adnc.Usr.Application.Contracts.Dtos; using Adnc.Usr.Application.Contracts.Services; using Adnc.WebApi.Shared; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs index 46e4cdd6..fa19ccc6 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs @@ -13,8 +13,10 @@ using Adnc.Infra.Mq; using Adnc.Infra.Repository; using Autofac; using Autofac.Extras.DynamicProxy; +using DotNetCore.CAP; using FluentValidation; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; @@ -32,7 +34,6 @@ namespace Adnc.Application.Shared private readonly Assembly _repoAssemblieToScan; private readonly Assembly _domainAssemblieToScan; private readonly IConfigurationSection _redisSection; - private readonly string _appModuleName; protected AdncApplicationModule(Type modelType, IConfiguration configuration, IServiceInfo serviceInfo, bool isDddDevelopment = false) { @@ -43,7 +44,6 @@ namespace Adnc.Application.Shared else _repoAssemblieToScan = Assembly.Load(_appAssemblieToScan.FullName.Replace(".Application", ".Repository")); - _appModuleName = serviceInfo.ShortName; _redisSection = configuration.GetRedisSection(); } @@ -139,7 +139,7 @@ namespace Adnc.Application.Shared #endregion register cacheservice/bloomfilter } - private void LoadDepends(ContainerBuilder builder) + protected virtual void LoadDepends(ContainerBuilder builder) { builder.RegisterModuleIfNotRegistered(new AdncInfraEventBusModule(_appAssemblieToScan)); builder.RegisterModuleIfNotRegistered(new AutoMapperModule(_appAssemblieToScan)); diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs index a3a437d0..e09ad50f 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs @@ -33,7 +33,6 @@ namespace Adnc.Application.Shared.Dtos this.XData = xData; } - [NotNull] public IReadOnlyList Data { get => _data; diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AbstractAppService.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AbstractAppService.cs index e008ce0b..7c182e63 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AbstractAppService.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AbstractAppService.cs @@ -1,6 +1,6 @@ using Adnc.Infra.Mapper; -using JetBrains.Annotations; using System; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Net; diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AppServiceResult.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AppServiceResult.cs index d1049d41..2438a132 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AppServiceResult.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Services/AppServiceResult.cs @@ -1,5 +1,5 @@ -using JetBrains.Annotations; -using System; +using System; +using System.Diagnostics.CodeAnalysis; namespace Adnc.Application.Shared.Services { diff --git a/src/ServerApi/Services/Shared/Adnc.Shared/Consts/CachingConsts/CachingConsts.Com.cs b/src/ServerApi/Services/Shared/Adnc.Shared/Consts/CachingConsts/CachingConsts.Com.cs index d1d1dac8..1ab521ef 100644 --- a/src/ServerApi/Services/Shared/Adnc.Shared/Consts/CachingConsts/CachingConsts.Com.cs +++ b/src/ServerApi/Services/Shared/Adnc.Shared/Consts/CachingConsts/CachingConsts.Com.cs @@ -2,6 +2,8 @@ { public class CachingConsts { + protected CachingConsts() { } + public const string LinkChar = ":"; public const int OneYear = 365 * 24 * 60 * 60; diff --git a/src/ServerApi/Services/Shared/Adnc.Shared/RpcServices/Rtos/DictRto.cs b/src/ServerApi/Services/Shared/Adnc.Shared/RpcServices/Rtos/DictRto.cs index f64afb6f..9245479c 100644 --- a/src/ServerApi/Services/Shared/Adnc.Shared/RpcServices/Rtos/DictRto.cs +++ b/src/ServerApi/Services/Shared/Adnc.Shared/RpcServices/Rtos/DictRto.cs @@ -1,5 +1,4 @@ -using JetBrains.Annotations; -using System; +using System; using System.Collections.Generic; namespace Adnc.Shared.RpcServices.Rtos @@ -18,7 +17,6 @@ namespace Adnc.Shared.RpcServices.Rtos private IReadOnlyList _data = Array.Empty(); - [NotNull] public IReadOnlyList Children { get => _data; diff --git a/src/ServerApi/build/version.props b/src/ServerApi/build/version.props index 64e85eff..3ed9a346 100644 --- a/src/ServerApi/build/version.props +++ b/src/ServerApi/build/version.props @@ -3,7 +3,7 @@ 0 8 6 - 0 + 2 $(VersionMajor).$(VersionMinor).$(VersionPatch) -- Gitee From fcc46ad86938a22287cf2e2accd8be2ed40c0216 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Tue, 12 Oct 2021 21:51:20 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20CapDashboardAuthorizat?= =?UTF-8?q?ionFilter=20ip=20=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Shared/Adnc.Application.Shared/AdncApplicationModule.cs | 2 -- .../Authorize/CapDashboardAuthorizationFilter.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs index fa19ccc6..9579db1c 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs @@ -13,10 +13,8 @@ using Adnc.Infra.Mq; using Adnc.Infra.Repository; using Autofac; using Autofac.Extras.DynamicProxy; -using DotNetCore.CAP; using FluentValidation; using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Authorize/CapDashboardAuthorizationFilter.cs b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Authorize/CapDashboardAuthorizationFilter.cs index 0023e578..bd91af8a 100644 --- a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Authorize/CapDashboardAuthorizationFilter.cs +++ b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Authorize/CapDashboardAuthorizationFilter.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Authorization { //这里定义capdashboard外网验证,需要完善 //默认内网可以访问 - if (context.Request.LocalIpAddress == "127.0.0.0.1") + if (context.Request.LocalIpAddress == "127.0.0.1") { return await Task.FromResult(true); } -- Gitee From ebd4bc88bb69e66e59c72250927fc4fa89515fc3 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Tue, 12 Oct 2021 21:59:03 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=B6=88=E9=99=A4sonar=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/Adnc.UnitTest/EfCoreRepositoryTests.cs | 32 ++++++++++----------- test/Adnc.UnitTest/UnitOfWorkTests.cs | 4 ++- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/test/Adnc.UnitTest/EfCoreRepositoryTests.cs b/test/Adnc.UnitTest/EfCoreRepositoryTests.cs index b2dd4a13..de573d54 100644 --- a/test/Adnc.UnitTest/EfCoreRepositoryTests.cs +++ b/test/Adnc.UnitTest/EfCoreRepositoryTests.cs @@ -544,7 +544,9 @@ namespace Adnc.UnitTest.EFCore throw new Exception(); +#pragma warning disable CS0162 // 检测到无法访问的代码 _unitOfWork.Commit(); +#pragma warning restore CS0162 // 检测到无法访问的代码 } catch (Exception) { @@ -570,36 +572,34 @@ namespace Adnc.UnitTest.EFCore { var account = "alpha008"; - using (var db = await _dbContext.Database.BeginTransactionAsync()) - { - //_unitOfWork.BeginTransaction(); + using var db = await _dbContext.Database.BeginTransactionAsync(); + //_unitOfWork.BeginTransaction(); - await _customerRsp.DeleteRangeAsync(x => x.Id <= 10000); + await _customerRsp.DeleteRangeAsync(x => x.Id <= 10000); - var id = IdGenerater.GetNextId(); - var customer = new Customer() { Id = id, Account = account, Nickname = "招财猫", Realname = "张发财", FinanceInfo = new CustomerFinance { Id = id, Account = account, Balance = 0 } }; + var id = IdGenerater.GetNextId(); + var customer = new Customer() { Id = id, Account = account, Nickname = "招财猫", Realname = "张发财", FinanceInfo = new CustomerFinance { Id = id, Account = account, Balance = 0 } }; - _dbContext.Add(customer); + _dbContext.Add(customer); - await _dbContext.SaveChangesAsync(); + await _dbContext.SaveChangesAsync(); - var id2 = IdGenerater.GetNextId(); - var customer2 = new Customer() { Id = id2, Account = account, Nickname = "招财猫02", Realname = "张发财02", FinanceInfo = new CustomerFinance { Id = id2, Account = account, Balance = 0 } }; + var id2 = IdGenerater.GetNextId(); + var customer2 = new Customer() { Id = id2, Account = account, Nickname = "招财猫02", Realname = "张发财02", FinanceInfo = new CustomerFinance { Id = id2, Account = account, Balance = 0 } }; - _dbContext.Add(customer2); - //_unitOfWork.Commit(); + _dbContext.Add(customer2); + //_unitOfWork.Commit(); - await _dbContext.SaveChangesAsync(); + await _dbContext.SaveChangesAsync(); - await db.CommitAsync(); - } + await db.CommitAsync(); } [Fact] public async Task TestAutoTransactions() { var defaultAutoTransaction = _dbContext.Database.AutoTransactionsEnabled; - if (defaultAutoTransaction == false) + if (!defaultAutoTransaction) _dbContext.Database.AutoTransactionsEnabled = true; var id = IdGenerater.GetNextId(); diff --git a/test/Adnc.UnitTest/UnitOfWorkTests.cs b/test/Adnc.UnitTest/UnitOfWorkTests.cs index 2e25806f..297506a0 100644 --- a/test/Adnc.UnitTest/UnitOfWorkTests.cs +++ b/test/Adnc.UnitTest/UnitOfWorkTests.cs @@ -14,7 +14,7 @@ namespace Adnc.UnitTest.CoreService private readonly ITestOutputHelper _output; private readonly IOperater _userContext; private readonly IEfRepository _cusRsp; - private CoreServiceFixture _fixture; + private readonly CoreServiceFixture _fixture; public UnitOfWorkTests(CoreServiceFixture fixture, ITestOutputHelper output) { @@ -56,6 +56,8 @@ namespace Adnc.UnitTest.CoreService //bool exists = await _cusRsp.AnyAsync(c => c.Id == id); // Assert.True(exists); Assert.True(true); + + await Task.CompletedTask; } } } \ No newline at end of file -- Gitee From 5627dc42e126bcfa91963628c7ad56eefbd0c577 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Tue, 12 Oct 2021 21:59:37 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E6=B6=88=E9=99=A4sonar=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extentions/IQueryableExtentions.cs | 104 +++++++++--------- .../Dtos/PageModelDto.cs | 22 ---- 2 files changed, 52 insertions(+), 74 deletions(-) diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs index 0de7fce5..a3b66ac8 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Repository/IRepositories/Extentions/IQueryableExtentions.cs @@ -2447,6 +2447,58 @@ namespace System.Linq : source); } + /// + /// Specifies related entities to include in the query results. The navigation property to be included is + /// specified starting with the type of entity being queried (). Further + /// navigation properties to be included can be appended, separated by the '.' character. + /// + /// + /// + /// The following query shows including a single level of related entities: + /// + /// context.Blogs.Include("Posts") + /// + /// The following query shows including two levels of entities on the same branch: + /// + /// context.Blogs.Include("Posts.Tags") + /// + /// The following query shows including multiple levels and branches of related data: + /// + /// + /// context.Blogs + /// .Include("Posts.Tags.TagInfo') + /// .Include("Contributors") + /// + /// + /// The type of entity being queried. + /// The source query. + /// A string of '.' separated navigation property names to be included. + /// A new query with the related data included. + /// + /// or is . + /// + /// + /// is empty or whitespace. + /// + public static IQueryable Include( + [NotNull] this IQueryable source, + [NotNull][NotParameterized] string navigationPropertyPath) + where TEntity : class + { + Check.NotNull(source, nameof(source)); + Check.NotEmpty(navigationPropertyPath, nameof(navigationPropertyPath)); + + return + source.Provider is EntityQueryProvider + ? source.Provider.CreateQuery( + Expression.Call( + instance: null, + method: StringIncludeMethodInfo.MakeGenericMethod(typeof(TEntity)), + arg0: source.Expression, + arg1: Expression.Constant(navigationPropertyPath))) + : source; + } + // A version of Include that doesn't set the navigation as loaded internal static IIncludableQueryable NotQuiteInclude( [NotNull] this IQueryable source, @@ -2629,58 +2681,6 @@ namespace System.Linq mi => mi.GetParameters().Any( pi => pi.Name == "navigationPropertyPath" && pi.ParameterType == typeof(string))); - /// - /// Specifies related entities to include in the query results. The navigation property to be included is - /// specified starting with the type of entity being queried (). Further - /// navigation properties to be included can be appended, separated by the '.' character. - /// - /// - /// - /// The following query shows including a single level of related entities: - /// - /// context.Blogs.Include("Posts") - /// - /// The following query shows including two levels of entities on the same branch: - /// - /// context.Blogs.Include("Posts.Tags") - /// - /// The following query shows including multiple levels and branches of related data: - /// - /// - /// context.Blogs - /// .Include("Posts.Tags.TagInfo') - /// .Include("Contributors") - /// - /// - /// The type of entity being queried. - /// The source query. - /// A string of '.' separated navigation property names to be included. - /// A new query with the related data included. - /// - /// or is . - /// - /// - /// is empty or whitespace. - /// - public static IQueryable Include( - [NotNull] this IQueryable source, - [NotNull][NotParameterized] string navigationPropertyPath) - where TEntity : class - { - Check.NotNull(source, nameof(source)); - Check.NotEmpty(navigationPropertyPath, nameof(navigationPropertyPath)); - - return - source.Provider is EntityQueryProvider - ? source.Provider.CreateQuery( - Expression.Call( - instance: null, - method: StringIncludeMethodInfo.MakeGenericMethod(typeof(TEntity)), - arg0: source.Expression, - arg1: Expression.Constant(navigationPropertyPath))) - : source; - } - #endregion Include #region Auto included navigations diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs index e09ad50f..a736e0c1 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Dtos/PageModelDto.cs @@ -58,26 +58,4 @@ namespace Adnc.Application.Shared.Dtos public dynamic XData { get; set; } } - - //[Serializable] - //public class PageModelDto : PageModelDto - //{ - // public PageModelDto(SearchPagedDto search, IReadOnlyList data, int count, dynamic xData = null) - // : this(search.PageIndex, search.PageSize, data, count) - // { - // } - - // public PageModelDto(int pageIndex, int pageSize, IReadOnlyList data, int count, dynamic xData = null) - // : base(pageIndex, pageSize, data, count) - // { - // this.XData = xData; - // } - - // public TXData XData { get; set; } - - // public static PageModelDto Convert(PageModelDto source, TXData xData) - // { - // return new PageModelDto(source.PageIndex, source.PageSize, source.Data, source.TotalCount, xData); - // } - //} } \ No newline at end of file -- Gitee From e3d33ee0b28e53ac0212e578fe1e811c1a7f4688 Mon Sep 17 00:00:00 2001 From: zoupengfei-lab <74526210+zoupengfei-lab@users.noreply.github.com> Date: Wed, 13 Oct 2021 17:27:51 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Hangfire=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=B0=83=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ServerApi/Adnc.sln | 11 ++ .../Adnc.Infra.Caching.csproj | 1 + .../Serialization/DefaultJsonSerializer.cs | 11 +- .../Configuration/ConfigurationExtensions.cs | 5 + .../Adnc.Infra.Hangfire.csproj | 17 +++ .../FileConfigurationProvider.cs | 141 +++++++++++++++++ .../Configuration/IConfigurationProvider.cs | 16 ++ .../JsonConfigurationProvider.cs | 75 +++++++++ .../Configuration/RecurringJobJsonOptions.cs | 83 ++++++++++ .../Adnc.Infra.Hangfire/CronJob.cs | 111 ++++++++++++++ .../HangfireApplicationBuilderExtensions.cs | 45 ++++++ .../IGlobalConfigurationExtensions.cs | 89 +++++++++++ .../Extensions/TypeExtensions.cs | 73 +++++++++ .../Adnc.Infra.Hangfire/HangfireConfig.cs | 44 ++++++ .../Adnc.Infra.Hangfire/HangfireModule.cs | 32 ++++ .../Adnc.Infra.Hangfire/IRecurringJob.cs | 16 ++ .../IRecurringJobBuilder.cs | 22 +++ .../IRecurringJobInfoStorage.cs | 38 +++++ .../IRecurringJobRegistry.cs | 34 +++++ .../IRecurringSchedulingJobs.cs | 6 + .../PerformContextExtensions.cs | 95 ++++++++++++ .../RecurringJobAttribute.cs | 30 ++++ .../RecurringJobBuilder.cs | 88 +++++++++++ .../Adnc.Infra.Hangfire/RecurringJobInfo.cs | 44 ++++++ .../RecurringJobInfoStorage.cs | 142 ++++++++++++++++++ .../RecurringJobRegistry.cs | 91 +++++++++++ .../TimeZoneInfoConverter.cs | 49 ++++++ .../appsettings.development.json | 12 ++ .../appsettings.development.json | 12 ++ .../appsettings.development.json | 12 ++ .../appsettings.development.json | 12 ++ .../appsettings.development.json | 12 ++ .../Adnc.Application.Shared.csproj | 1 + .../AdncApplicationModule.cs | 4 +- .../Extensions/ApplicationBuilderExtension.cs | 12 +- .../Extensions/ServiceCollectionExtension.cs | 1 + .../SharedServicesRegistration.cs | 64 +++++++- 37 files changed, 1543 insertions(+), 8 deletions(-) create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Adnc.Infra.Hangfire.csproj create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/FileConfigurationProvider.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/IConfigurationProvider.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/JsonConfigurationProvider.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/RecurringJobJsonOptions.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/CronJob.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/HangfireApplicationBuilderExtensions.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/IGlobalConfigurationExtensions.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/TypeExtensions.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireConfig.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJob.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobBuilder.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobInfoStorage.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobRegistry.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringSchedulingJobs.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/PerformContextExtensions.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobAttribute.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobBuilder.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfo.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfoStorage.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobRegistry.cs create mode 100644 src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/TimeZoneInfoConverter.cs diff --git a/src/ServerApi/Adnc.sln b/src/ServerApi/Adnc.sln index e21c3a47..faa9dd0f 100644 --- a/src/ServerApi/Adnc.sln +++ b/src/ServerApi/Adnc.sln @@ -111,6 +111,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bulid", "Bulid", "{5F46F98A build\version.props = build\version.props EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adnc.Infra.Hangfire", "Infrastructures\Adnc.Infra.Hangfire\Adnc.Infra.Hangfire.csproj", "{69B2785A-E760-4097-80AB-F047AF7979E4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -455,6 +457,14 @@ Global {382E6BFE-F809-4E29-BEAB-57BA9C7FA69B}.Release|Any CPU.Build.0 = Release|Any CPU {382E6BFE-F809-4E29-BEAB-57BA9C7FA69B}.Release|x64.ActiveCfg = Release|Any CPU {382E6BFE-F809-4E29-BEAB-57BA9C7FA69B}.Release|x64.Build.0 = Release|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Debug|x64.ActiveCfg = Debug|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Debug|x64.Build.0 = Debug|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Release|Any CPU.Build.0 = Release|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Release|x64.ActiveCfg = Release|Any CPU + {69B2785A-E760-4097-80AB-F047AF7979E4}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -508,6 +518,7 @@ Global {538DC339-CEBD-46D4-9241-39EC28D8B8EB} = {3B899133-BEAC-4438-977F-B28FDFF3AE27} {F75F21E6-2C4A-45D0-9DF6-19A097254FE1} = {1D4DB6DE-CDE0-4B60-A71D-DFD792C6D864} {382E6BFE-F809-4E29-BEAB-57BA9C7FA69B} = {1D4DB6DE-CDE0-4B60-A71D-DFD792C6D864} + {69B2785A-E760-4097-80AB-F047AF7979E4} = {3B899133-BEAC-4438-977F-B28FDFF3AE27} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3DED72E8-74C9-4A51-A9CE-62ECFEEA1921} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Adnc.Infra.Caching.csproj b/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Adnc.Infra.Caching.csproj index 8653ceb6..2e2c14f0 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Adnc.Infra.Caching.csproj +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Adnc.Infra.Caching.csproj @@ -24,5 +24,6 @@ + \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Core/Serialization/DefaultJsonSerializer.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Core/Serialization/DefaultJsonSerializer.cs index a41144c7..633fe53f 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Core/Serialization/DefaultJsonSerializer.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Caching/Core/Serialization/DefaultJsonSerializer.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json; namespace Adnc.Infra.Caching.Core.Serialization { @@ -8,27 +9,27 @@ namespace Adnc.Infra.Caching.Core.Serialization public T Deserialize(byte[] bytes) { - throw new NotImplementedException(); + return JsonSerializer.Deserialize(bytes); } public object Deserialize(byte[] bytes, Type type) { - throw new NotImplementedException(); + return JsonSerializer.Deserialize(bytes); } public object DeserializeObject(ArraySegment value) { - throw new NotImplementedException(); + return JsonSerializer.Deserialize(value); } public byte[] Serialize(T value) { - throw new NotImplementedException(); + return JsonSerializer.SerializeToUtf8Bytes(value); } public ArraySegment SerializeObject(object obj) { - throw new NotImplementedException(); + return JsonSerializer.SerializeToUtf8Bytes(obj); } } } \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Core/Microsoft/Extensions/Configuration/ConfigurationExtensions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Core/Microsoft/Extensions/Configuration/ConfigurationExtensions.cs index be519fe0..8796620d 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Core/Microsoft/Extensions/Configuration/ConfigurationExtensions.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Core/Microsoft/Extensions/Configuration/ConfigurationExtensions.cs @@ -57,5 +57,10 @@ { return configuration.GetSection("ThreadPoolSettings"); } + + public static IConfigurationSection GetHangfireSection(this IConfiguration configuration) + { + return configuration.GetSection("Hangfire"); + } } } \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Adnc.Infra.Hangfire.csproj b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Adnc.Infra.Hangfire.csproj new file mode 100644 index 00000000..4ff19fef --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Adnc.Infra.Hangfire.csproj @@ -0,0 +1,17 @@ + + + + netstandard2.1 + Adnc.Infra.Hangfire + Adnc.Infra.Hangfire + + + + + + + + + + + \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/FileConfigurationProvider.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/FileConfigurationProvider.cs new file mode 100644 index 00000000..a5f9a1ca --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/FileConfigurationProvider.cs @@ -0,0 +1,141 @@ +using Hangfire.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security; +using System.Threading; + +namespace Hangfire.Configuration +{ + /// + /// Represents a base class for file based . + /// + public abstract class FileConfigurationProvider : IConfigurationProvider, IDisposable + { + private const int NumberOfRetries = 3; + private const int DelayOnRetry = 1000; + + private static readonly ILog _logger = LogProvider.For(); + private FileSystemWatcher _fileWatcher; + private readonly object _fileWatcherLock = new object(); + + /// + /// Initializes a new + /// + /// The source settings file. + /// Whether the should be reloaded if the file changes. + public FileConfigurationProvider(string configFile, bool reloadOnChange = true) + : this(new FileInfo(configFile), reloadOnChange) { } + + /// + /// Initializes a new + /// + /// The source settings . + /// Whether the should be reloaded if the file changes. + public FileConfigurationProvider(FileInfo fileInfo, bool reloadOnChange = true) + { + if (fileInfo == null) throw new ArgumentNullException(nameof(fileInfo)); + + if (!fileInfo.Exists) + throw new FileNotFoundException($"The json file {fileInfo.FullName} does not exist."); + + ConfigFile = fileInfo; + + ReloadOnChange = reloadOnChange; + + Initialize(); + } + private void Initialize() + { + _fileWatcher = new FileSystemWatcher(ConfigFile.DirectoryName, ConfigFile.Name); + _fileWatcher.EnableRaisingEvents = ReloadOnChange; + _fileWatcher.Changed += OnChanged; + _fileWatcher.Error += OnError; + } + private void OnError(object sender, ErrorEventArgs e) + { + _logger.InfoException($"File {ConfigFile} occurred errors.", e.GetException()); + } + + private void OnChanged(object sender, FileSystemEventArgs e) + { + lock (_fileWatcherLock) + { + _logger.Info($"File {e.Name} changed, try to reload configuration again..."); + + var recurringJobInfos = Load().ToArray(); + + if (recurringJobInfos == null || recurringJobInfos.Length == 0) return; + + CronJob.AddOrUpdate(recurringJobInfos); + } + } + + /// + /// configuraion file + /// + public virtual FileInfo ConfigFile { get; set; } + + /// + /// Whether the should be reloaded. + /// + public virtual bool ReloadOnChange { get; set; } + + /// + /// Loads the data for this provider. + /// + /// The list of . + public abstract IEnumerable Load(); + + /// + /// Reads from config file. + /// + /// The string content reading from file. + protected virtual string ReadFromFile() + { + if (!ConfigFile.Exists) + throw new FileNotFoundException($"The json file {ConfigFile.FullName} does not exist."); + + var content = string.Empty; + + for (int i = 0; i < NumberOfRetries; ++i) + { + try + { + // Do stuff with file + using (var file = ConfigFile.OpenRead()) + using (StreamReader reader = new StreamReader(file)) + content = reader.ReadToEnd(); + + break; // When done we can break loop + } + catch (Exception ex) when ( + ex is IOException || + ex is SecurityException || + ex is UnauthorizedAccessException) + { + // Swallow the exception. + _logger.DebugException($"read file {ConfigFile} error.", ex); + + // You may check error code to filter some exceptions, not every error + // can be recovered. + if (i == NumberOfRetries) // Last one, (re)throw exception and exit + throw; + + Thread.Sleep(DelayOnRetry); + } + } + + return content; + } + + /// + /// Disposes the file watcher + /// + public virtual void Dispose() + { + _fileWatcher?.Dispose(); + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/IConfigurationProvider.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/IConfigurationProvider.cs new file mode 100644 index 00000000..fe6c22b4 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/IConfigurationProvider.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace Hangfire.Configuration +{ + /// + /// Provides configuration for for Hangfire. + /// + public interface IConfigurationProvider + { + /// + /// Loads configuration values from the source represented by this . + /// + /// The list of . + IEnumerable Load(); + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/JsonConfigurationProvider.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/JsonConfigurationProvider.cs new file mode 100644 index 00000000..a3f19a85 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/JsonConfigurationProvider.cs @@ -0,0 +1,75 @@ +using Hangfire.Common; +using Hangfire.States; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Hangfire.Configuration +{ + /// + /// Represents a JSON file provider as an . + /// + public class JsonConfigurationProvider : FileConfigurationProvider + { + /// + /// Initializes a new . + /// + /// The source settings file. + /// Whether the should be reloaded if the file changes. + public JsonConfigurationProvider(string configFile, bool reloadOnChange = true) + : base(configFile, reloadOnChange) { } + + /// + /// Loads the for this source. + /// + /// The list of for this provider. + public override IEnumerable Load() + { + var jsonContent = ReadFromFile(); + + if (string.IsNullOrWhiteSpace(jsonContent)) throw new Exception("Json file content is empty."); + + var jsonOptions = JobHelper.FromJson>(jsonContent); + + foreach (var o in jsonOptions) + yield return Convert(o); + } + + private RecurringJobInfo Convert(RecurringJobJsonOptions option) + { + ValidateJsonOptions(option); + + return new RecurringJobInfo + { + RecurringJobId = option.JobName, +#if NET45 + Method = option.JobType.GetMethod(nameof(IRecurringJob.Execute)), +#else + Method = option.JobType.GetTypeInfo().GetDeclaredMethod(nameof(IRecurringJob.Execute)), +#endif + Cron = option.Cron, + Queue = option.Queue ?? EnqueuedState.DefaultQueue, + TimeZone = option.TimeZone ?? TimeZoneInfo.Utc, + JobData = option.JobData, + Enable = option.Enable ?? true + }; + } + + private void ValidateJsonOptions(RecurringJobJsonOptions option) + { + if (option == null) throw new ArgumentNullException(nameof(option)); + + if (string.IsNullOrWhiteSpace(option.JobName)) + { + throw new Exception($"The json token 'job-name' is null, empty, or consists only of white-space."); + } + + if (!option.JobType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IRecurringJob))) + { + throw new Exception($"job-type: {option.JobType} must impl the interface {typeof(IRecurringJob)}."); + } + + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/RecurringJobJsonOptions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/RecurringJobJsonOptions.cs new file mode 100644 index 00000000..ea292dae --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Configuration/RecurringJobJsonOptions.cs @@ -0,0 +1,83 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; + +namespace Hangfire.Configuration +{ + /// + /// json configuration settings. + /// + public class RecurringJobJsonOptions + { + /// + /// The job name represents for + /// + [JsonProperty("job-name")] +#if !NET45 + [JsonRequired] +#endif + public string JobName { get; set; } + /// + /// The job type while impl the interface . + /// + [JsonProperty("job-type")] +#if !NET45 + [JsonRequired] +#endif + public Type JobType { get; set; } + + /// + /// Cron expressions + /// + [JsonProperty("cron-expression")] +#if !NET45 + [JsonRequired] +#endif + public string Cron { get; set; } + + /// + /// The value of can be created by + /// + [JsonProperty("timezone")] + [JsonConverter(typeof(TimeZoneInfoConverter))] + public TimeZoneInfo TimeZone { get; set; } + /// + /// Whether the property can be serialized or not. + /// + /// true if value not null, otherwise false. + public bool ShouldSerializeTimeZone() => TimeZone != null; + /// + /// Hangfire queue name + /// + [JsonProperty("queue")] + public string Queue { get; set; } + /// + /// Whether the property can be serialized or not. + /// + /// true if value not null or empty, otherwise false. + public bool ShouldSerializeQueue() => !string.IsNullOrEmpty(Queue); + /// + /// The data persisted in storage. + /// + [JsonProperty("job-data")] + public IDictionary JobData { get; set; } + /// + /// Whether the property can be serialized or not. + /// + /// true if value not null or count is zero, otherwise false. + public bool ShouldSerializeJobData() => JobData != null && JobData.Count > 0; + + /// + /// Whether the can be added/updated, + /// default value is true, if false it will be deleted automatically. + /// + [JsonProperty("enable")] + public bool? Enable { get; set; } + + /// + /// Whether the property can be serialized or not. + /// + /// true if value is not null, otherwise false. + public bool ShouldSerializeEnable() => Enable.HasValue; + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/CronJob.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/CronJob.cs new file mode 100644 index 00000000..ca7822a3 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/CronJob.cs @@ -0,0 +1,111 @@ +using Hangfire.Configuration; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Hangfire +{ + /// + /// The helper class to build automatically. + /// + public class CronJob + { + /// + /// Builds automatically within specified interface or class. + /// + /// Specified interface or class + public static void AddOrUpdate(params Type[] types) + { + AddOrUpdate(() => types); + } + + /// + /// Builds automatically within specified interface or class. + /// + /// The provider to get specified interfaces or class. + public static void AddOrUpdate(Func> typesProvider) + { + if (typesProvider == null) throw new ArgumentNullException(nameof(typesProvider)); + + IRecurringJobBuilder builder = new RecurringJobBuilder(); + + builder.Build(typesProvider); + } + + /// + /// Builds automatically by using multiple JSON configuration files. + /// + /// The array of json files. + /// Whether the should be reloaded if the file changes. + public static void AddOrUpdate(string[] jsonFiles, bool reloadOnChange = true) + { + if (jsonFiles == null) throw new ArgumentNullException(nameof(jsonFiles)); + + foreach (var jsonFile in jsonFiles) + AddOrUpdate(jsonFile, reloadOnChange); + } + /// + /// Builds automatically by using a JSON configuration. + /// + /// Json file for configuration. + /// Whether the should be reloaded if the file changes. + public static void AddOrUpdate(string jsonFile, bool reloadOnChange = true) + { + if (string.IsNullOrWhiteSpace(jsonFile)) throw new ArgumentNullException(nameof(jsonFile)); + + var configFile = File.Exists(jsonFile) ? jsonFile : + Path.Combine( +#if NET45 + AppDomain.CurrentDomain.BaseDirectory, +#else + AppContext.BaseDirectory, +#endif + jsonFile); + + + if (!File.Exists(configFile)) throw new FileNotFoundException($"The json file {configFile} does not exist."); + + IConfigurationProvider provider = new JsonConfigurationProvider(configFile, reloadOnChange); + + AddOrUpdate(provider); + } + + /// + /// Builds automatically with . + /// + /// + public static void AddOrUpdate(IConfigurationProvider provider) + { + if (provider == null) throw new ArgumentNullException(nameof(provider)); + + IRecurringJobBuilder builder = new RecurringJobBuilder(); + + AddOrUpdate(provider.Load()); + } + + /// + /// Builds automatically with the collection of . + /// + /// The collection of . + public static void AddOrUpdate(IEnumerable recurringJobInfos) + { + if (recurringJobInfos == null) throw new ArgumentNullException(nameof(recurringJobInfos)); + + IRecurringJobBuilder builder = new RecurringJobBuilder(); + + builder.Build(() => recurringJobInfos); + } + + /// + /// Builds automatically with the array of . + /// + /// The array of . + public static void AddOrUpdate(params RecurringJobInfo[] recurringJobInfos) + { + if (recurringJobInfos == null) throw new ArgumentNullException(nameof(recurringJobInfos)); + + AddOrUpdate(recurringJobInfos.AsEnumerable()); + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/HangfireApplicationBuilderExtensions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/HangfireApplicationBuilderExtensions.cs new file mode 100644 index 00000000..3899a123 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/HangfireApplicationBuilderExtensions.cs @@ -0,0 +1,45 @@ +using Adnc.Infra.Core; +using Hangfire.Dashboard.BasicAuthorization; +using Microsoft.AspNetCore.Builder; +using System.Linq; + +namespace Hangfire +{ + public static class HangfireApplicationBuilderExtensions + { + public static IApplicationBuilder UseHangfireDashboard(this IApplicationBuilder builder, IServiceInfo serviceInfo) + { + var options = new DashboardOptions + { + AppPath = $"/{serviceInfo.ShortName}/hangfire", + DashboardTitle = $"{serviceInfo.Description}任务控制台", + DisplayStorageConnectionString = false + }; + + builder.UseHangfireDashboard($"/{serviceInfo.ShortName}/hangfire", options); + + return builder; + } + + public static IApplicationBuilder UseHangfireDashboard(this IApplicationBuilder builder, IServiceInfo serviceInfo, params Authorize[] authorize) + { + var options = new DashboardOptions + { + AppPath = $"/{serviceInfo.ShortName}/hangfire", + DashboardTitle = $"{serviceInfo.Description}任务控制台", + DisplayStorageConnectionString = false + }; + if (authorize.Any()) + { + options.Authorization = authorize.Select(s => + new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions + { + Users = new[] { new BasicAuthAuthorizationUser { Login = s.Login, PasswordClear = s.Password } } + })).ToArray(); + } + builder.UseHangfireDashboard($"/{serviceInfo.ShortName}/hangfire", options); + + return builder; + } + } +} \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/IGlobalConfigurationExtensions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/IGlobalConfigurationExtensions.cs new file mode 100644 index 00000000..7e570ce5 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/IGlobalConfigurationExtensions.cs @@ -0,0 +1,89 @@ +using Hangfire.Configuration; +using System; +using System.Collections.Generic; + +namespace Hangfire +{ + /// + /// Hangfire extensions. + /// + public static class IGlobalConfigurationExtensions + { + /// + /// Builds automatically within specified interface or class. + /// To the Hangfire client, alternatively way is to use the class to add or update . + /// + /// + /// Specified interface or class + /// + public static IGlobalConfiguration UseRecurringJob(this IGlobalConfiguration configuration, params Type[] types) + { + return UseRecurringJob(configuration, () => types); + } + + /// + /// Builds automatically within specified interface or class. + /// To the Hangfire client, alternatively way is to use the class to add or update . + /// + /// + /// The provider to get specified interfaces or class. + /// + public static IGlobalConfiguration UseRecurringJob(this IGlobalConfiguration configuration, Func> typesProvider) + { + if (typesProvider == null) throw new ArgumentNullException(nameof(typesProvider)); + + CronJob.AddOrUpdate(typesProvider); + + return configuration; + } + /// + /// Builds automatically by using a JSON configuration. + /// To the Hangfire client, alternatively way is to use the class to add or update . + /// + /// . + /// Json file for configuration. + /// Whether the should be reloaded if the file changes. + /// + public static IGlobalConfiguration UseRecurringJob(this IGlobalConfiguration configuration, string jsonFile, bool reloadOnChange = true) + { + if (string.IsNullOrWhiteSpace(jsonFile)) throw new ArgumentNullException(nameof(jsonFile)); + + CronJob.AddOrUpdate(jsonFile, reloadOnChange); + + return configuration; + } + + /// + /// Builds automatically by using multiple JSON configuration files. + /// To the Hangfire client, alternatively way is to use the class to add or update . + /// + /// . + /// The array of json files. + /// Whether the should be reloaded if the file changes. + /// + public static IGlobalConfiguration UseRecurringJob(this IGlobalConfiguration configuration, string[] jsonFiles, bool reloadOnChange = true) + { + if (jsonFiles == null) throw new ArgumentNullException(nameof(jsonFiles)); + + CronJob.AddOrUpdate(jsonFiles, reloadOnChange); + + return configuration; + } + + /// + /// Builds automatically with . + /// To the Hangfire client, alternatively way is to use the class to add or update . + /// + /// . + /// + /// . + public static IGlobalConfiguration UseRecurringJob(this IGlobalConfiguration configuration, IConfigurationProvider provider) + { + if (provider == null) throw new ArgumentNullException(nameof(provider)); + + CronJob.AddOrUpdate(provider); + + return configuration; + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/TypeExtensions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/TypeExtensions.cs new file mode 100644 index 00000000..f15322b6 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/Extensions/TypeExtensions.cs @@ -0,0 +1,73 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace Hangfire +{ + internal static class TypeExtensions + { + public static string GetRecurringJobId(this MethodInfo method) + { + return $"{method.DeclaringType.ToGenericTypeString()}.{method.Name}"; + } + /// + /// Fork the extension method from + /// https://github.com/HangfireIO/Hangfire/blob/master/src/Hangfire.Core/Common/TypeExtensions.cs + /// + /// + /// + public static string ToGenericTypeString(this Type type) + { + if (!type.GetTypeInfo().IsGenericType) + { + return type.GetFullNameWithoutNamespace() + .ReplacePlusWithDotInNestedTypeName(); + } + + return type.GetGenericTypeDefinition() + .GetFullNameWithoutNamespace() + .ReplacePlusWithDotInNestedTypeName() + .ReplaceGenericParametersInGenericTypeName(type); + } + private static string GetFullNameWithoutNamespace(this Type type) + { + if (type.IsGenericParameter) + { + return type.Name; + } + + const int dotLength = 1; + // ReSharper disable once PossibleNullReferenceException + return !String.IsNullOrEmpty(type.Namespace) + ? type.FullName.Substring(type.Namespace.Length + dotLength) + : type.FullName; + } + private static string ReplacePlusWithDotInNestedTypeName(this string typeName) + { + return typeName.Replace('+', '.'); + } + private static string ReplaceGenericParametersInGenericTypeName(this string typeName, Type type) + { + var genericArguments = type.GetTypeInfo().GetAllGenericArguments(); + + const string regexForGenericArguments = @"`[1-9]\d*"; + + var rgx = new Regex(regexForGenericArguments); + + typeName = rgx.Replace(typeName, match => + { + var currentGenericArgumentNumbers = int.Parse(match.Value.Substring(1)); + var currentArguments = string.Join(",", genericArguments.Take(currentGenericArgumentNumbers).Select(ToGenericTypeString)); + genericArguments = genericArguments.Skip(currentGenericArgumentNumbers).ToArray(); + return string.Concat("<", currentArguments, ">"); + }); + + return typeName; + } + public static Type[] GetAllGenericArguments(this TypeInfo type) + { + return type.GenericTypeArguments.Length > 0 ? type.GenericTypeArguments : type.GenericTypeParameters; + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireConfig.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireConfig.cs new file mode 100644 index 00000000..1ac42cf8 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireConfig.cs @@ -0,0 +1,44 @@ +namespace Hangfire +{ + public class HangfireConfig + { + /// + /// 数据库连接字符串 + /// + public string ConnectionString { get; set; } + + /// + /// 连接检查超时,单位分钟默认一分钟 + /// + public int ConnectionCheckTimeout { get; set; } = 1; + + /// + /// 队列轮询间隔 + /// + public int QueuePollInterval { get; set; } = 1; + + /// + /// 任务超时过期时间,单位分钟默认一小时 + /// + public int JobTimeout { get; set; } = 60; + + /// + /// 登录授权 + /// + public Authorize[] Authorize { get; set; } = new[] { new Authorize { Login = "adnc", Password = "123456" } }; + } + + public class Authorize + { + /// + /// 登录账号 + /// + public string Login { get; set; } + + /// + /// 密码 + /// + public string Password { get; set; } + } +} + diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs new file mode 100644 index 00000000..6ef3e1ab --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs @@ -0,0 +1,32 @@ +using Autofac; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Hangfire +{ + /// + /// Hangfire 模块注册 + /// + public class HangfireModule : Autofac.Module + { + private readonly IEnumerable _assembliesToScan; + + public HangfireModule(IEnumerable assembliesToScan) + { + _assembliesToScan = assembliesToScan; + } + + public HangfireModule(params Assembly[] assembliesToScan) : this((IEnumerable)assembliesToScan) + { + } + + protected override void Load(ContainerBuilder builder) + { + builder.RegisterAssemblyTypes(_assembliesToScan.ToArray()) + .Where(t => t.IsAssignableTo() && t.IsAssignableTo() && !t.IsAbstract) + .AsImplementedInterfaces() + .SingleInstance(); + } + } +} \ No newline at end of file diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJob.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJob.cs new file mode 100644 index 00000000..79db8524 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJob.cs @@ -0,0 +1,16 @@ +using Hangfire.Server; + +namespace Hangfire +{ + /// + /// Provides a unified interface to build hangfire , similar to quartz.net. + /// + public interface IRecurringJob + { + /// + /// Execute the . + /// + /// The context to . + void Execute(PerformContext context); + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobBuilder.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobBuilder.cs new file mode 100644 index 00000000..93d3121a --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobBuilder.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace Hangfire +{ + /// + /// Build automatically. + /// + public interface IRecurringJobBuilder + { + /// + /// Create with the provider for specified interface or class. + /// + /// Specified interface or class + void Build(Func> typesProvider); + /// + /// Create with the provider for specified list . + /// + /// The provider to get list/> + void Build(Func> recurringJobInfoProvider); + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobInfoStorage.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobInfoStorage.cs new file mode 100644 index 00000000..3f1a33ac --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobInfoStorage.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace Hangfire +{ + /// + /// The storage APIs for . + /// + public interface IRecurringJobInfoStorage : IDisposable + { + /// + /// Finds all from storage. + /// + /// The collection of + IEnumerable FindAll(); + + /// + /// Finds by jobId. + /// The job id is associated with + /// + /// The specified + /// + RecurringJobInfo FindByJobId(string jobId); + + /// + /// Finds by recurringJobId. + /// + /// The specified identifier of the RecurringJob. + /// + RecurringJobInfo FindByRecurringJobId(string recurringJobId); + + /// + /// Sets to storage which associated with . + /// + /// The specified identifier of the RecurringJob. + void SetJobData(RecurringJobInfo recurringJobInfo); + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobRegistry.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobRegistry.cs new file mode 100644 index 00000000..00e4e057 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringJobRegistry.cs @@ -0,0 +1,34 @@ +using System; +using System.Reflection; + +namespace Hangfire +{ + /// + /// Register dynamically. + /// + public interface IRecurringJobRegistry + { + /// + /// Register RecurringJob via . + /// + /// the specified method + /// Cron expressions + /// + /// Queue name + void Register(MethodInfo method, string cron, TimeZoneInfo timeZone, string queue); + /// + /// Register RecurringJob via . + /// + /// The identifier of the RecurringJob + /// the specified method + /// Cron expressions + /// + /// Queue name + void Register(string recurringJobId, MethodInfo method, string cron, TimeZoneInfo timeZone, string queue); + /// + /// Register RecurringJob via . + /// + /// info. + void Register(RecurringJobInfo recurringJobInfo); + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringSchedulingJobs.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringSchedulingJobs.cs new file mode 100644 index 00000000..1547e6ae --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/IRecurringSchedulingJobs.cs @@ -0,0 +1,6 @@ +namespace Hangfire +{ + public interface IRecurringSchedulingJobs + { + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/PerformContextExtensions.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/PerformContextExtensions.cs new file mode 100644 index 00000000..5ad87000 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/PerformContextExtensions.cs @@ -0,0 +1,95 @@ +using Hangfire.Common; +using Hangfire.Server; +using System; +using System.Collections.Generic; + +namespace Hangfire +{ + /// + /// Extensions for . + /// + public static class PerformContextExtensions + { + /// + /// Gets job data from storage associated with . + /// + /// The . + /// The dictionary key from the property + /// The value from the property + public static object GetJobData(this PerformContext context, string name) + { + if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); + + var jobData = GetJobData(context); + + if (jobData == null) return null; + + return jobData.ContainsKey(name) ? jobData[name] : null; + } + + /// + /// Gets job data from storage associated with . + /// + /// The specified type to json value. + /// The . + /// The dictionary key from the property + /// The value from the property + public static T GetJobData(this PerformContext context, string name) + { + var o = GetJobData(context, name); + + var json = JobHelper.ToJson(o); + + return JobHelper.FromJson(json); + } + + /// + /// Gets job data from storage associated with . + /// + /// The . + /// The job data from storage. + public static IDictionary GetJobData(this PerformContext context) + { + using (var storage = new RecurringJobInfoStorage(context.Connection)) + { + return storage.FindByJobId(context.BackgroundJob.Id)?.JobData; + } + } + + /// + /// Persists job data to storage associated with . + /// + /// The . + /// The dictionary key from the property + /// The persisting value. + public static void SetJobData(this PerformContext context, string name, object value) + { + if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); + + SetJobData(context, new Dictionary { [name] = value }); + } + + /// + /// Persists job data to storage associated with . + /// + /// The . + /// The dictionary value to be added or updated. + public static void SetJobData(this PerformContext context, IDictionary jobData) + { + if (jobData == null) throw new ArgumentNullException(nameof(jobData)); + + using (var storage = new RecurringJobInfoStorage(context.Connection)) + { + var recurringJobInfo = storage.FindByJobId(context.BackgroundJob.Id); + + if (recurringJobInfo.JobData == null) + recurringJobInfo.JobData = new Dictionary(); + + foreach (var kv in jobData) + recurringJobInfo.JobData[kv.Key] = kv.Value; + + storage.SetJobData(recurringJobInfo); + } + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobAttribute.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobAttribute.cs new file mode 100644 index 00000000..c53d34e0 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobAttribute.cs @@ -0,0 +1,30 @@ +using Hangfire.States; +using System; + +namespace Hangfire +{ + [AttributeUsage(AttributeTargets.Method)] + public class RecurringJobAttribute : Attribute + { + /// + /// RecurringJob 的标识 + /// + public string RecurringJobId { get; set; } + /// + /// Cron 表达式 + /// + public string Cron { get; set; } + /// + /// 队列名称 + /// + public string Queue { get; set; } = EnqueuedState.DefaultQueue; + /// + /// 时区信息,默认值为 + /// + public TimeZoneInfo TimeZone { get; set; } = TimeZoneInfo.Utc; + /// + /// 是否自动构建RecurringJob,默认为true,为false,它将被自动删除。 + /// + public bool Enabled { get; set; } = true; + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobBuilder.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobBuilder.cs new file mode 100644 index 00000000..57600fdf --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobBuilder.cs @@ -0,0 +1,88 @@ +using Hangfire.States; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Hangfire +{ + /// + /// Build automatically, interface. + /// + public class RecurringJobBuilder : IRecurringJobBuilder + { + private IRecurringJobRegistry _registry; + + /// + /// Initializes a new instance of the . + /// + public RecurringJobBuilder() : this(new RecurringJobRegistry()) { } + + /// + /// Initializes a new instance of the with . + /// + /// interface. + public RecurringJobBuilder(IRecurringJobRegistry registry) + { + _registry = registry; + } + /// + /// Create with the provider for specified interface or class. + /// + /// Specified interface or class + public void Build(Func> typesProvider) + { + if (typesProvider == null) throw new ArgumentNullException(nameof(typesProvider)); + + foreach (var type in typesProvider()) + { + foreach (var method in type.GetTypeInfo().DeclaredMethods) + { + if (!method.IsDefined(typeof(RecurringJobAttribute), false)) continue; + + var attribute = method.GetCustomAttribute(false); + + if (attribute == null) continue; + + if (string.IsNullOrWhiteSpace(attribute.RecurringJobId)) + { + attribute.RecurringJobId = method.GetRecurringJobId(); + } + + if (!attribute.Enabled) + { + RecurringJob.RemoveIfExists(attribute.RecurringJobId); + continue; + } + _registry.Register( + attribute.RecurringJobId, + method, + attribute.Cron, + attribute.TimeZone, + attribute.Queue ?? EnqueuedState.DefaultQueue); + } + } + } + /// + /// Create with the provider for specified list . + /// + /// The provider to get list. + public void Build(Func> recurringJobInfoProvider) + { + if (recurringJobInfoProvider == null) throw new ArgumentNullException(nameof(recurringJobInfoProvider)); + + foreach (RecurringJobInfo recurringJobInfo in recurringJobInfoProvider()) + { + if (string.IsNullOrWhiteSpace(recurringJobInfo.RecurringJobId)) + { + throw new Exception($"The property of {nameof(recurringJobInfo.RecurringJobId)} is null, empty, or consists only of white-space."); + } + if (!recurringJobInfo.Enable) + { + RecurringJob.RemoveIfExists(recurringJobInfo.RecurringJobId); + continue; + } + _registry.Register(recurringJobInfo); + } + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfo.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfo.cs new file mode 100644 index 00000000..5d68bfa0 --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfo.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Hangfire +{ + /// + /// It is used to build + /// with . + /// + public class RecurringJobInfo + { + /// + /// The identifier of the RecurringJob + /// + public string RecurringJobId { get; set; } + /// + /// Cron expressions + /// + public string Cron { get; set; } + /// + /// TimeZoneInfo + /// + public TimeZoneInfo TimeZone { get; set; } + /// + /// Queue name + /// + public string Queue { get; set; } + /// + /// Method to execute while running. + /// + public MethodInfo Method { get; set; } + /// + /// The data persisted in storage. + /// + public IDictionary JobData { get; set; } + + /// + /// Whether the can be added/updated, + /// default value is true, if false it will be deleted automatically. + /// + public bool Enable { get; set; } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfoStorage.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfoStorage.cs new file mode 100644 index 00000000..43a4e60b --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobInfoStorage.cs @@ -0,0 +1,142 @@ +using Hangfire.Common; +using Hangfire.Storage; +using System; +using System.Collections.Generic; + +namespace Hangfire +{ + /// + /// The storage APIs for . + /// + public class RecurringJobInfoStorage : IRecurringJobInfoStorage + { + private static readonly TimeSpan LockTimeout = TimeSpan.FromMinutes(1); + + private readonly IStorageConnection _connection; + + /// + /// Initializes a new + /// + public RecurringJobInfoStorage() : this(JobStorage.Current.GetConnection()) { } + + /// + /// Initializes a new + /// + /// + public RecurringJobInfoStorage(IStorageConnection connection) + { + if (connection == null) throw new ArgumentNullException(nameof(connection)); + + _connection = connection; + } + + /// + /// Finds all from storage. + /// + /// The collection of + public IEnumerable FindAll() + { + var recurringJobIds = _connection.GetAllItemsFromSet("recurring-jobs"); + + foreach (var recurringJobId in recurringJobIds) + { + var recurringJob = _connection.GetAllEntriesFromHash($"recurring-job:{recurringJobId}"); + + if (recurringJob == null) continue; + + yield return InternalFind(recurringJobId, recurringJob); + } + } + + /// + /// Finds by jobId. + /// The job id is associated with + /// + /// The specified + /// + public RecurringJobInfo FindByJobId(string jobId) + { + if (string.IsNullOrEmpty(jobId)) throw new ArgumentNullException(nameof(jobId)); + + var paramValue = _connection.GetJobParameter(jobId, "RecurringJobId"); + + if (string.IsNullOrEmpty(paramValue)) throw new Exception($"There is not RecurringJobId with associated BackgroundJob Id:{jobId}"); + + var recurringJobId = JobHelper.FromJson(paramValue); + + return FindByRecurringJobId(recurringJobId); + } + + /// + /// Finds by recurringJobId. + /// + /// The specified identifier of the RecurringJob. + /// + public RecurringJobInfo FindByRecurringJobId(string recurringJobId) + { + if (string.IsNullOrEmpty(recurringJobId)) throw new ArgumentNullException(nameof(recurringJobId)); + + var recurringJob = _connection.GetAllEntriesFromHash($"recurring-job:{recurringJobId}"); + + if (recurringJob == null) return null; + + return InternalFind(recurringJobId, recurringJob); + } + + private RecurringJobInfo InternalFind(string recurringJobId, Dictionary recurringJob) + { + if (string.IsNullOrEmpty(recurringJobId)) throw new ArgumentNullException(nameof(recurringJobId)); + if (recurringJob == null) throw new ArgumentNullException(nameof(recurringJob)); + + var serializedJob = JobHelper.FromJson(recurringJob["Job"]); + var job = serializedJob.Deserialize(); + + return new RecurringJobInfo + { + RecurringJobId = recurringJobId, + Cron = recurringJob["Cron"], + TimeZone = recurringJob.ContainsKey("TimeZoneId") + ? TimeZoneInfo.FindSystemTimeZoneById(recurringJob["TimeZoneId"]) + : TimeZoneInfo.Utc, + Queue = recurringJob["Queue"], + Method = job.Method, + Enable = recurringJob.ContainsKey(nameof(RecurringJobInfo.Enable)) + ? JobHelper.FromJson(recurringJob[nameof(RecurringJobInfo.Enable)]) + : true, + JobData = recurringJob.ContainsKey(nameof(RecurringJobInfo.JobData)) + ? JobHelper.FromJson>(recurringJob[nameof(RecurringJobInfo.JobData)]) + : null + }; + } + + /// + /// Sets to storage which associated with . + /// + /// The specified identifier of the RecurringJob. + public void SetJobData(RecurringJobInfo recurringJobInfo) + { + if (recurringJobInfo == null) throw new ArgumentNullException(nameof(recurringJobInfo)); + + if (recurringJobInfo.JobData == null || recurringJobInfo.JobData.Count == 0) return; + + using (_connection.AcquireDistributedLock($"recurringjobextensions-jobdata:{recurringJobInfo.RecurringJobId}", LockTimeout)) + { + var changedFields = new Dictionary + { + [nameof(RecurringJobInfo.Enable)] = JobHelper.ToJson(recurringJobInfo.Enable), + [nameof(RecurringJobInfo.JobData)] = JobHelper.ToJson(recurringJobInfo.JobData) + }; + + _connection.SetRangeInHash($"recurring-job:{recurringJobInfo.RecurringJobId}", changedFields); + } + } + + /// + /// Disposes storage connection. + /// + public void Dispose() + { + _connection?.Dispose(); + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobRegistry.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobRegistry.cs new file mode 100644 index 00000000..8ec2ae3a --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/RecurringJobRegistry.cs @@ -0,0 +1,91 @@ +using System; +using System.Linq.Expressions; +using System.Reflection; + +namespace Hangfire +{ + /// + /// Register dynamically. + /// interface. + /// + public class RecurringJobRegistry : IRecurringJobRegistry + { + /// + /// Register RecurringJob via . + /// + /// The specified method + /// Cron expressions + /// + /// Queue name + public void Register(MethodInfo method, string cron, TimeZoneInfo timeZone, string queue) + { + if (method == null) throw new ArgumentNullException(nameof(method)); + if (cron == null) throw new ArgumentNullException(nameof(cron)); + if (timeZone == null) throw new ArgumentNullException(nameof(timeZone)); + if (queue == null) throw new ArgumentNullException(nameof(queue)); + + var jobId = method.GetRecurringJobId(); + + Register(jobId, method, cron, timeZone, queue); + } + /// + /// Register RecurringJob via . + /// + /// The identifier of the RecurringJob + /// the specified method + /// Cron expressions + /// + /// Queue name + public void Register(string recurringJobId, MethodInfo method, string cron, TimeZoneInfo timeZone, string queue) + { + if (recurringJobId == null) throw new ArgumentNullException(nameof(recurringJobId)); + if (method == null) throw new ArgumentNullException(nameof(method)); + if (cron == null) throw new ArgumentNullException(nameof(cron)); + if (timeZone == null) throw new ArgumentNullException(nameof(timeZone)); + if (queue == null) throw new ArgumentNullException(nameof(queue)); + + var parameters = method.GetParameters(); + + Expression[] args = new Expression[parameters.Length]; + + for (int i = 0; i < parameters.Length; i++) + { + args[i] = Expression.Default(parameters[i].ParameterType); + } + + var x = Expression.Parameter(method.DeclaringType, "x"); + + var methodCall = method.IsStatic ? Expression.Call(method, args) : Expression.Call(x, method, args); + + var addOrUpdate = Expression.Call( + typeof(RecurringJob), + nameof(RecurringJob.AddOrUpdate), + new Type[] { method.DeclaringType }, + new Expression[] + { + Expression.Constant(recurringJobId), + Expression.Lambda(methodCall, x), + Expression.Constant(cron), + Expression.Constant(timeZone), + Expression.Constant(queue) + }); + + Expression.Lambda(addOrUpdate).Compile().DynamicInvoke(); + } + /// + /// Register RecurringJob via . + /// + /// info. + public void Register(RecurringJobInfo recurringJobInfo) + { + if (recurringJobInfo == null) throw new ArgumentNullException(nameof(recurringJobInfo)); + + Register(recurringJobInfo.RecurringJobId, recurringJobInfo.Method, recurringJobInfo.Cron, recurringJobInfo.TimeZone, recurringJobInfo.Queue); + + using (var storage = new RecurringJobInfoStorage()) + { + storage.SetJobData(recurringJobInfo); + } + } + } +} diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/TimeZoneInfoConverter.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/TimeZoneInfoConverter.cs new file mode 100644 index 00000000..d99c771a --- /dev/null +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/TimeZoneInfoConverter.cs @@ -0,0 +1,49 @@ +using Newtonsoft.Json; +using System; + +namespace Hangfire +{ + /// + /// Converts to and from JSON + /// + public class TimeZoneInfoConverter : JsonConverter + { + /// + /// Determines whether this instance can convert the specified + /// + /// Type of the object. + /// true if this instance can convert the specified ; otherwise, false. + public override bool CanConvert(Type objectType) + { + return objectType == typeof(TimeZoneInfo); + } + /// + /// Reads the JSON representation of the object. + /// + /// The to read from + /// Type of the object + /// The existing value of object being read + /// The calling serializer + /// The object value + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + + if (reader.Value == null) return null; + + return TimeZoneInfo.FindSystemTimeZoneById(reader.Value.ToString()); + } + /// + /// Writes the JSON representation of the . + /// + /// The to write to + /// The value + /// The calling serializer + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var o = value as TimeZoneInfo; + + writer.WriteValue(o.StandardName); + } + } +} diff --git a/src/ServerApi/Services/Adnc.Cus/Adnc.Cus.WebApi/appsettings.development.json b/src/ServerApi/Services/Adnc.Cus/Adnc.Cus.WebApi/appsettings.development.json index 728fc40d..f3dca347 100644 --- a/src/ServerApi/Services/Adnc.Cus/Adnc.Cus.WebApi/appsettings.development.json +++ b/src/ServerApi/Services/Adnc.Cus/Adnc.Cus.WebApi/appsettings.development.json @@ -58,6 +58,18 @@ "CollectionNamingConvention": 2, "PluralizeCollectionNames": true }, + "Hangfire": { + "ConnectionString": "mongodb://alpha:football@106.14.139.201:13017/cus_dev?authSource=cus_dev", + "ConnectionCheckTimeout": 5, + "QueuePollInterval": 5, + "JobTimeout": 60, + "Authorize": [ + { + "Login": "adncdev", + "Password": "adncdev.123@123" + } + ] + }, "RabbitMq": { "HostName": "106.14.139.201", "VirtualHost": "vhost.adnc.dev", diff --git a/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.WebApi/appsettings.development.json b/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.WebApi/appsettings.development.json index b6db4873..c1e663ea 100644 --- a/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.WebApi/appsettings.development.json +++ b/src/ServerApi/Services/Adnc.Maint/Adnc.Maint.WebApi/appsettings.development.json @@ -58,6 +58,18 @@ "CollectionNamingConvention": 2, "PluralizeCollectionNames": true }, + "Hangfire": { + "ConnectionString": "mongodb://alpha:football@106.14.139.201:13017/maint_dev?authSource=maint_dev", + "ConnectionCheckTimeout": 5, + "QueuePollInterval": 5, + "JobTimeout": 60, + "Authorize": [ + { + "Login": "adncdev", + "Password": "adncdev.123@123" + } + ] + }, "RabbitMq": { "HostName": "106.14.139.201", "VirtualHost": "vhost.adnc.dev", diff --git a/src/ServerApi/Services/Adnc.Ord/Adnc.Ord.WebApi/appsettings.development.json b/src/ServerApi/Services/Adnc.Ord/Adnc.Ord.WebApi/appsettings.development.json index 5cdaf7d8..12993ad0 100644 --- a/src/ServerApi/Services/Adnc.Ord/Adnc.Ord.WebApi/appsettings.development.json +++ b/src/ServerApi/Services/Adnc.Ord/Adnc.Ord.WebApi/appsettings.development.json @@ -57,6 +57,18 @@ "CollectionNamingConvention": 2, "PluralizeCollectionNames": true }, + "Hangfire": { + "ConnectionString": "mongodb://alpha:football@106.14.139.201:13017/ord_dev?authSource=ord_dev", + "ConnectionCheckTimeout": 5, + "QueuePollInterval": 5, + "JobTimeout": 60, + "Authorize": [ + { + "Login": "adncdev", + "Password": "adncdev.123@123" + } + ] + }, "RabbitMq": { "HostName": "106.14.139.201", "VirtualHost": "vhost.adnc.dev", diff --git a/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/appsettings.development.json b/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/appsettings.development.json index 5abd1b60..d0335b7b 100644 --- a/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/appsettings.development.json +++ b/src/ServerApi/Services/Adnc.Usr/Adnc.Usr.WebApi/appsettings.development.json @@ -58,6 +58,18 @@ "CollectionNamingConvention": 2, "PluralizeCollectionNames": true }, + "Hangfire": { + "ConnectionString": "mongodb://alpha:football@106.14.139.201:13017/usr_dev?authSource=usr_dev", + "ConnectionCheckTimeout": 5, + "QueuePollInterval": 5, + "JobTimeout": 60, + "Authorize": [ + { + "Login": "adncdev", + "Password": "adncdev.123@123" + } + ] + }, "RabbitMq": { "HostName": "106.14.139.201", "VirtualHost": "vhost.adnc.dev", diff --git a/src/ServerApi/Services/Adnc.Whse/Adnc.Whse.WebApi/appsettings.development.json b/src/ServerApi/Services/Adnc.Whse/Adnc.Whse.WebApi/appsettings.development.json index 11a9a0f8..ff5ebc1b 100644 --- a/src/ServerApi/Services/Adnc.Whse/Adnc.Whse.WebApi/appsettings.development.json +++ b/src/ServerApi/Services/Adnc.Whse/Adnc.Whse.WebApi/appsettings.development.json @@ -57,6 +57,18 @@ "CollectionNamingConvention": 2, "PluralizeCollectionNames": true }, + "Hangfire": { + "ConnectionString": "mongodb://alpha:football@106.14.139.201:13017/whse_dev?authSource=whse_dev", + "ConnectionCheckTimeout": 5, + "QueuePollInterval": 5, + "JobTimeout": 60, + "Authorize": [ + { + "Login": "adncdev", + "Password": "adncdev.123@123" + } + ] + }, "RabbitMq": { "HostName": "106.14.139.201", "VirtualHost": "vhost.adnc.dev", diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Adnc.Application.Shared.csproj b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Adnc.Application.Shared.csproj index 87038bfe..b1f569b9 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/Adnc.Application.Shared.csproj +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/Adnc.Application.Shared.csproj @@ -13,6 +13,7 @@ + diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs index 46e4cdd6..8311bc7a 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs @@ -14,6 +14,7 @@ using Adnc.Infra.Repository; using Autofac; using Autofac.Extras.DynamicProxy; using FluentValidation; +using Hangfire; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; @@ -144,8 +145,9 @@ namespace Adnc.Application.Shared builder.RegisterModuleIfNotRegistered(new AdncInfraEventBusModule(_appAssemblieToScan)); builder.RegisterModuleIfNotRegistered(new AutoMapperModule(_appAssemblieToScan)); builder.RegisterModuleIfNotRegistered(new AdncInfraCachingModule(_redisSection)); + builder.RegisterModuleIfNotRegistered(new HangfireModule(_appAssemblieToScan)); - if(_domainAssemblieToScan!=null) + if (_domainAssemblieToScan!=null) { var modelType = _domainAssemblieToScan.GetTypes().FirstOrDefault(x => x.IsAssignableTo() && !x.IsAbstract); builder.RegisterModuleIfNotRegistered(System.Activator.CreateInstance(modelType) as Autofac.Module); diff --git a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs index bfd8dea3..e6c0f4e5 100644 --- a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs +++ b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs @@ -1,6 +1,7 @@ using Adnc.Infra.Consul; using Adnc.Infra.Core; using Adnc.WebApi.Shared.Middleware; +using Hangfire; using HealthChecks.UI.Client; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Hosting; @@ -29,8 +30,17 @@ namespace Microsoft.AspNetCore.Builder var configuration = app.ApplicationServices.GetService(); var environment = app.ApplicationServices.GetService(); var serviceInfo = app.ApplicationServices.GetService(); + var hangfireConfig = configuration.GetHangfireSection().Get(); - if (environment.IsDevelopment()) IdentityModelEventSource.ShowPII = true; + if (environment.IsDevelopment()) + { + IdentityModelEventSource.ShowPII = true; + app.UseHangfireDashboard(serviceInfo); + } + else + { + app.UseHangfireDashboard(serviceInfo, hangfireConfig.Authorize); + } DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); defaultFilesOptions.DefaultFileNames.Clear(); diff --git a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs index 3437a6d1..58c71d23 100644 --- a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs +++ b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs @@ -51,6 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection _srvRegistration.AddEfCoreContext(); _srvRegistration.AddMongoContext(); _srvRegistration.AddSwaggerGen(); + _srvRegistration.AddHangfire(); completedExecute?.Invoke(_srvRegistration); diff --git a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/SharedServicesRegistration.cs b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/SharedServicesRegistration.cs index 63df7f99..41ae6485 100644 --- a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/SharedServicesRegistration.cs +++ b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/SharedServicesRegistration.cs @@ -17,6 +17,11 @@ using DotNetCore.CAP; using DotNetCore.CAP.Dashboard; using DotNetCore.CAP.Dashboard.NodeDiscovery; using FluentValidation.AspNetCore; +using Hangfire; +using Hangfire.Console; +using Hangfire.Mongo; +using Hangfire.Mongo.Migration.Strategies; +using Hangfire.Mongo.Migration.Strategies.Backup; using MicroElements.Swashbuckle.FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; @@ -33,6 +38,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; +using MongoDB.Driver; using Polly; using Polly.Timeout; using Refit; @@ -62,6 +68,7 @@ namespace Adnc.WebApi.Shared protected readonly IServiceCollection _services; protected readonly IHostEnvironment _environment; protected readonly IServiceInfo _serviceInfo; + protected internal IEnumerable _schedulingJobs; /// /// 服务注册与系统配置 @@ -79,6 +86,7 @@ namespace Adnc.WebApi.Shared _environment = environment; _services = services; _serviceInfo = serviceInfo; + _schedulingJobs = Enumerable.Empty(); } /// @@ -487,7 +495,7 @@ namespace Adnc.WebApi.Shared /// 在注册中心注册的服务名称,或者服务的Url /// Polly策略 public virtual void AddRpcService(string serviceName - , List> policies) + , List> policies) where TRpcService : class, IRpcService { var prefix = serviceName.Substring(0, 7); @@ -509,6 +517,60 @@ namespace Adnc.WebApi.Shared policies?.ForEach(policy => clientbuilder.AddPolicyHandler(policy)); } + + /// + /// 添加任务调度 + /// + /// + public virtual void AddSchedulingJobs() + where TSchedulingJob : class, IRecurringSchedulingJobs + { + _schedulingJobs = _schedulingJobs.Concat(new[] { typeof(TSchedulingJob) }); + } + + /// + /// 注册 Hangfire 任务调度 + /// + public virtual void AddHangfire() + { + var hangfireConfig = _configuration.GetHangfireSection().Get(); + + var mongoUrlBuilder = new MongoUrlBuilder(hangfireConfig.ConnectionString); + var mongoClient = new MongoClient(mongoUrlBuilder.ToMongoUrl()); + + _services.AddHangfire(config => + { + config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170); + config.UseSimpleAssemblyNameTypeSerializer(); + config.UseRecommendedSerializerSettings(); + // 设置 MongoDB 为持久化存储器 + config.UseMongoStorage(mongoClient, mongoUrlBuilder.DatabaseName, new MongoStorageOptions + { + MigrationOptions = new MongoMigrationOptions + { + MigrationStrategy = new MigrateMongoMigrationStrategy(), + BackupStrategy = new CollectionMongoBackupStrategy() + }, + ConnectionCheckTimeout = TimeSpan.FromMinutes(hangfireConfig.ConnectionCheckTimeout), + QueuePollInterval = TimeSpan.FromMinutes(hangfireConfig.QueuePollInterval), + CheckConnection = true, + }) + // 任务超时时间 + .JobExpirationTimeout = TimeSpan.FromMinutes(hangfireConfig.JobTimeout); + // 打印日志到控制面板和在线进度条展示 + config.UseConsole(); + config.UseRecurringJob(_schedulingJobs.ToArray()); + }); + // 将 Hangfire 服务添加为后台托管服务 + _services.AddHangfireServer((service, options) => + { + options.ServerName = $"{_serviceInfo.FullName.Replace(".", "/")}"; + options.ShutdownTimeout = TimeSpan.FromMinutes(10); + // 最大 Job 处理并发数量的阈值,根据机子处理器数量设置或默认20 + options.WorkerCount = Math.Max(Environment.ProcessorCount, 20); + }); + } + /// /// 生成默认的Polly策略 /// -- Gitee From 09882060ab73896d7754968a111aab7d89025a58 Mon Sep 17 00:00:00 2001 From: "Alpha.Yu" Date: Wed, 13 Oct 2021 23:47:50 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20Hangfire=20=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=B3=A8=E5=86=8C=E4=BB=A3=E7=A0=81=E3=80=82=E8=AF=A5?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E8=BF=98=E9=9C=80=E8=A6=81=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=B8=8E=E6=B5=8B=E8=AF=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{HangfireModule.cs => AdncInfraHangfireModule.cs} | 6 +++--- .../{AutoMapperModule.cs => AdncInfraAutoMapperModule.cs} | 6 +++--- .../Shared/Adnc.Application.Shared/AdncApplicationModule.cs | 4 ++-- .../Extensions/ApplicationBuilderExtension.cs | 4 ++-- .../Extensions/ServiceCollectionExtension.cs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) rename src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/{HangfireModule.cs => AdncInfraHangfireModule.cs} (73%) rename src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/{AutoMapperModule.cs => AdncInfraAutoMapperModule.cs} (90%) diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/AdncInfraHangfireModule.cs similarity index 73% rename from src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs rename to src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/AdncInfraHangfireModule.cs index 6ef3e1ab..d0728413 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/HangfireModule.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Hangfire/AdncInfraHangfireModule.cs @@ -8,16 +8,16 @@ namespace Hangfire /// /// Hangfire 模块注册 /// - public class HangfireModule : Autofac.Module + public class AdncInfraHangfireModule : Autofac.Module { private readonly IEnumerable _assembliesToScan; - public HangfireModule(IEnumerable assembliesToScan) + public AdncInfraHangfireModule(IEnumerable assembliesToScan) { _assembliesToScan = assembliesToScan; } - public HangfireModule(params Assembly[] assembliesToScan) : this((IEnumerable)assembliesToScan) + public AdncInfraHangfireModule(params Assembly[] assembliesToScan) : this((IEnumerable)assembliesToScan) { } diff --git a/src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/AutoMapperModule.cs b/src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/AdncInfraAutoMapperModule.cs similarity index 90% rename from src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/AutoMapperModule.cs rename to src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/AdncInfraAutoMapperModule.cs index 72a35b07..c381cd2a 100644 --- a/src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/AutoMapperModule.cs +++ b/src/ServerApi/Infrastructures/Adnc.Infra.Mapper/AutoMapper/AdncInfraAutoMapperModule.cs @@ -12,16 +12,16 @@ namespace Adnc.Infra.Mapper.AutoMapper /// 注册automapper /// https://dotnetfalcon.com/autofac-support-for-automapper/ /// - public class AutoMapperModule : Autofac.Module + public class AdncInfraAutoMapperModule : Autofac.Module { private readonly IEnumerable assembliesToScan; - public AutoMapperModule(IEnumerable assembliesToScan) + public AdncInfraAutoMapperModule(IEnumerable assembliesToScan) { this.assembliesToScan = assembliesToScan; } - public AutoMapperModule(params Assembly[] assembliesToScan) : this((IEnumerable)assembliesToScan) + public AdncInfraAutoMapperModule(params Assembly[] assembliesToScan) : this((IEnumerable)assembliesToScan) { } diff --git a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs index 1f3dd923..266fe609 100644 --- a/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs +++ b/src/ServerApi/Services/Shared/Adnc.Application.Shared/AdncApplicationModule.cs @@ -141,9 +141,9 @@ namespace Adnc.Application.Shared protected virtual void LoadDepends(ContainerBuilder builder) { builder.RegisterModuleIfNotRegistered(new AdncInfraEventBusModule(_appAssemblieToScan)); - builder.RegisterModuleIfNotRegistered(new AutoMapperModule(_appAssemblieToScan)); + builder.RegisterModuleIfNotRegistered(new AdncInfraAutoMapperModule(_appAssemblieToScan)); builder.RegisterModuleIfNotRegistered(new AdncInfraCachingModule(_redisSection)); - builder.RegisterModuleIfNotRegistered(new HangfireModule(_appAssemblieToScan)); + //builder.RegisterModuleIfNotRegistered(new AdncInfraHangfireModule(_appAssemblieToScan)); if (_domainAssemblieToScan!=null) { diff --git a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs index e6c0f4e5..455c2d79 100644 --- a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs +++ b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ApplicationBuilderExtension.cs @@ -35,11 +35,11 @@ namespace Microsoft.AspNetCore.Builder if (environment.IsDevelopment()) { IdentityModelEventSource.ShowPII = true; - app.UseHangfireDashboard(serviceInfo); + //app.UseHangfireDashboard(serviceInfo); } else { - app.UseHangfireDashboard(serviceInfo, hangfireConfig.Authorize); + //app.UseHangfireDashboard(serviceInfo, hangfireConfig.Authorize); } DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); diff --git a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs index 58c71d23..640d5bfc 100644 --- a/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs +++ b/src/ServerApi/Services/Shared/Adnc.WebApi.Shared/Extensions/ServiceCollectionExtension.cs @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection _srvRegistration.AddEfCoreContext(); _srvRegistration.AddMongoContext(); _srvRegistration.AddSwaggerGen(); - _srvRegistration.AddHangfire(); + //_srvRegistration.AddHangfire(); completedExecute?.Invoke(_srvRegistration); -- Gitee