mirror of
				https://github.com/nsnail/NetAdmin.git
				synced 2025-11-01 03:35:28 +08:00 
			
		
		
		
	perf: ⚡ 事件总线精简优化
This commit is contained in:
		| @@ -32,7 +32,6 @@ global using Gurion.DataEncryption; | ||||
| global using Gurion.DataValidation; | ||||
| global using Gurion.DependencyInjection; | ||||
| global using Gurion.DynamicApiController; | ||||
| global using Gurion.EventBus; | ||||
| global using Gurion.SpecificationDocument; | ||||
| global using Gurion.UnifyResult; | ||||
| global using Mapster; | ||||
| @@ -58,6 +57,7 @@ global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Redis; | ||||
| global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Upload; | ||||
| global using NetAdmin.Infrastructure.Constant; | ||||
| global using NetAdmin.Infrastructure.Enums; | ||||
| global using NetAdmin.Infrastructure.EventBus; | ||||
| global using NetAdmin.Infrastructure.Exceptions; | ||||
| global using NetAdmin.Infrastructure.Extensions; | ||||
| global using NetAdmin.Infrastructure.Languages; | ||||
|   | ||||
| @@ -15,11 +15,6 @@ public sealed record CacheStatisticsRsp : DataAbstraction | ||||
|       , new("redis_version:(.+)", RegexOptions.Compiled)        // | ||||
|     ]; | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class. | ||||
|     /// </summary> | ||||
|     public CacheStatisticsRsp() { } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class. | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -7,11 +7,6 @@ namespace NetAdmin.Domain.Dto.Sys.Cache; | ||||
| /// </summary> | ||||
| public sealed record GetEntryRsp : DataAbstraction | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="GetEntryRsp" /> class. | ||||
|     /// </summary> | ||||
|     public GetEntryRsp() { } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     缓存值 | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -7,11 +7,6 @@ namespace NetAdmin.Domain.Dto.Sys.Menu; | ||||
| /// </summary> | ||||
| public sealed record MetaInfo : DataAbstraction | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="MetaInfo" /> class. | ||||
|     /// </summary> | ||||
|     public MetaInfo() { } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="MetaInfo" /> class. | ||||
|     /// </summary> | ||||
|   | ||||
							
								
								
									
										21
									
								
								src/backend/NetAdmin/NetAdmin.Domain/Events/EventData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/backend/NetAdmin/NetAdmin.Domain/Events/EventData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| namespace NetAdmin.Domain.Events; | ||||
|  | ||||
| /// <summary> | ||||
| ///     事件数据 | ||||
| /// </summary> | ||||
| public abstract record EventData<T> : DataAbstraction, IEventData<T> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="EventData{T}" /> class. | ||||
|     /// </summary> | ||||
|     protected EventData(T payLoad) | ||||
|     { | ||||
|         PayLoad = payLoad; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; init; } = DateTime.Now; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public T PayLoad { get; init; } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| namespace NetAdmin.Domain.Events; | ||||
|  | ||||
| /// <summary> | ||||
| ///     泛型事件源接口 | ||||
| /// </summary> | ||||
| public interface IEventSourceGeneric<out T> : IEventSource | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     事件承载(携带)数据 | ||||
|     /// </summary> | ||||
|     T Data { get; } | ||||
| } | ||||
| @@ -3,36 +3,9 @@ namespace NetAdmin.Domain.Events; | ||||
| /// <summary> | ||||
| ///     种子数据插入完毕事件 | ||||
| /// </summary> | ||||
| public sealed record SeedDataInsertedEvent : DataAbstraction, IEventSource | ||||
| public sealed record SeedDataInsertedEvent : EventData<int> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="SeedDataInsertedEvent" /> class. | ||||
|     /// </summary> | ||||
|     public SeedDataInsertedEvent(int insertedCount, bool isConsumeOnce = false) | ||||
|     { | ||||
|         IsConsumeOnce = isConsumeOnce; | ||||
|         InsertedCount = insertedCount; | ||||
|         CreatedTime   = DateTime.Now; | ||||
|         EventId       = nameof(SeedDataInsertedEvent); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string EventId { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public bool IsConsumeOnce { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CancellationToken CancellationToken { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     插入数量 | ||||
|     /// </summary> | ||||
|     public int InsertedCount { get; set; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public object Payload { get; init; } | ||||
|     public SeedDataInsertedEvent(int payLoad) // | ||||
|         : base(payLoad) { } | ||||
| } | ||||
| @@ -12,7 +12,6 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent | ||||
|         : base(e) | ||||
|     { | ||||
|         ElapsedMilliseconds = (long)((double)e.ElapsedTicks / Stopwatch.Frequency * 1_000); | ||||
|         EventId             = nameof(SqlCommandAfterEvent); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -24,6 +23,6 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent | ||||
|     /// <inheritdoc /> | ||||
|     public override string ToString() | ||||
|     { | ||||
|         return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, Sql, ElapsedMilliseconds); | ||||
|         return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, PayLoad, ElapsedMilliseconds); | ||||
|     } | ||||
| } | ||||
| @@ -8,13 +8,8 @@ public record SqlCommandBeforeEvent : SqlCommandEvent | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="SqlCommandBeforeEvent" /> class. | ||||
|     /// </summary> | ||||
|     public SqlCommandBeforeEvent(CommandBeforeEventArgs e) | ||||
|     { | ||||
|         Identifier  = e.Identifier; | ||||
|         Sql         = e.Command.ParameterFormat().RemoveWrapped(); | ||||
|         EventId     = nameof(SqlCommandBeforeEvent); | ||||
|         CreatedTime = DateTime.Now; | ||||
|     } | ||||
|     public SqlCommandBeforeEvent(CommandBeforeEventArgs e) // | ||||
|         : base(e.Command.ParameterFormat().RemoveWrapped(), e.Identifier) { } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override string ToString() | ||||
|   | ||||
| @@ -3,31 +3,17 @@ namespace NetAdmin.Domain.Events; | ||||
| /// <summary> | ||||
| ///     Sql命令事件 | ||||
| /// </summary> | ||||
| public abstract record SqlCommandEvent : DataAbstraction, IEventSource | ||||
| public abstract record SqlCommandEvent : EventData<string> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="SqlCommandEvent" /> class. | ||||
|     /// </summary> | ||||
|     protected SqlCommandEvent(bool isConsumeOnce = false) | ||||
|     protected SqlCommandEvent(string payLoad, Guid identifier) // | ||||
|         : base(payLoad) | ||||
|     { | ||||
|         IsConsumeOnce = isConsumeOnce; | ||||
|         Identifier = identifier; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public bool IsConsumeOnce { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CancellationToken CancellationToken { get; init; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; protected init; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string EventId { get; protected init; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public object Payload { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     标识符缩写 | ||||
|     /// </summary> | ||||
| @@ -37,9 +23,4 @@ public abstract record SqlCommandEvent : DataAbstraction, IEventSource | ||||
|     ///     标识符,可将 CommandBefore 与 CommandAfter 进行匹配 | ||||
|     /// </summary> | ||||
|     protected Guid Identifier { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     关联的Sql语句 | ||||
|     /// </summary> | ||||
|     protected string Sql { get; init; } | ||||
| } | ||||
| @@ -9,10 +9,7 @@ public sealed record SyncStructureAfterEvent : SyncStructureBeforeEvent | ||||
|     ///     Initializes a new instance of the <see cref="SyncStructureAfterEvent" /> class. | ||||
|     /// </summary> | ||||
|     public SyncStructureAfterEvent(SyncStructureBeforeEventArgs e) // | ||||
|         : base(e) | ||||
|     { | ||||
|         EventId = nameof(SyncStructureAfterEvent); | ||||
|     } | ||||
|         : base(e) { } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override string ToString() | ||||
|   | ||||
| @@ -8,11 +8,9 @@ public record SyncStructureBeforeEvent : SqlCommandEvent | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="SyncStructureBeforeEvent" /> class. | ||||
|     /// </summary> | ||||
|     public SyncStructureBeforeEvent(SyncStructureBeforeEventArgs e) | ||||
|     public SyncStructureBeforeEvent(SyncStructureBeforeEventArgs e) // | ||||
|         : base(null, e.Identifier) | ||||
|     { | ||||
|         Identifier  = e.Identifier; | ||||
|         EventId     = nameof(SyncStructureBeforeEvent); | ||||
|         CreatedTime = DateTime.Now; | ||||
|         EntityTypes = e.EntityTypes; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys; | ||||
| /// <summary> | ||||
| ///     请求日志事件 | ||||
| /// </summary> | ||||
| public sealed record RequestLogEvent : DataAbstraction, IEventSourceGeneric<CreateRequestLogReq> | ||||
| public sealed record RequestLogEvent : EventData<CreateRequestLogReq> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="RequestLogEvent" /> class. | ||||
|     /// </summary> | ||||
|     public RequestLogEvent(CreateRequestLogReq data, bool isConsumeOnce = false, object payload = null, DateTime createdTime = default | ||||
|                          , CancellationToken   cancellationToken = default) | ||||
|     { | ||||
|         Data              = data; | ||||
|         IsConsumeOnce     = isConsumeOnce; | ||||
|         Payload           = payload; | ||||
|         CreatedTime       = createdTime; | ||||
|         CancellationToken = cancellationToken; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CancellationToken CancellationToken { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CreateRequestLogReq Data { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string EventId => nameof(RequestLogEvent); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public bool IsConsumeOnce { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public object Payload { get; } | ||||
|     public RequestLogEvent(CreateRequestLogReq payLoad) // | ||||
|         : base(payLoad) { } | ||||
| } | ||||
| @@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys; | ||||
| /// <summary> | ||||
| ///     用户被创建事件 | ||||
| /// </summary> | ||||
| public sealed record UserCreatedEvent : DataAbstraction, IEventSourceGeneric<UserInfoRsp> | ||||
| public sealed record UserCreatedEvent : EventData<UserInfoRsp> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="UserCreatedEvent" /> class. | ||||
|     /// </summary> | ||||
|     public UserCreatedEvent(UserInfoRsp       data, DateTime createdTime = default, bool isConsumeOnce = false, object payload = null | ||||
|                           , CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         Data              = data; | ||||
|         CancellationToken = cancellationToken; | ||||
|         CreatedTime       = createdTime; | ||||
|         IsConsumeOnce     = isConsumeOnce; | ||||
|         Payload           = payload; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CancellationToken CancellationToken { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public UserInfoRsp Data { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string EventId => nameof(UserCreatedEvent); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public bool IsConsumeOnce { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public object Payload { get; } | ||||
|     public UserCreatedEvent(UserInfoRsp payLoad) // | ||||
|         : base(payLoad) { } | ||||
| } | ||||
| @@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys; | ||||
| /// <summary> | ||||
| ///     用户被更新事件 | ||||
| /// </summary> | ||||
| public sealed record UserUpdatedEvent : DataAbstraction, IEventSourceGeneric<UserInfoRsp> | ||||
| public sealed record UserUpdatedEvent : EventData<UserInfoRsp> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="UserUpdatedEvent" /> class. | ||||
|     /// </summary> | ||||
|     public UserUpdatedEvent(UserInfoRsp       data, DateTime createdTime = default, bool isConsumeOnce = false, object payload = null | ||||
|                           , CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         Data              = data; | ||||
|         CancellationToken = cancellationToken; | ||||
|         CreatedTime       = createdTime; | ||||
|         IsConsumeOnce     = isConsumeOnce; | ||||
|         Payload           = payload; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CancellationToken CancellationToken { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public UserInfoRsp Data { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string EventId => nameof(UserUpdatedEvent); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public bool IsConsumeOnce { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public object Payload { get; } | ||||
|     public UserUpdatedEvent(UserInfoRsp payLoad) // | ||||
|         : base(payLoad) { } | ||||
| } | ||||
| @@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys; | ||||
| /// <summary> | ||||
| ///     验证码创建事件 | ||||
| /// </summary> | ||||
| public sealed record VerifyCodeCreatedEvent : DataAbstraction, IEventSourceGeneric<QueryVerifyCodeRsp> | ||||
| public sealed record VerifyCodeCreatedEvent : EventData<QueryVerifyCodeRsp> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="VerifyCodeCreatedEvent" /> class. | ||||
|     /// </summary> | ||||
|     public VerifyCodeCreatedEvent(QueryVerifyCodeRsp data, DateTime createdTime = default, bool isConsumeOnce = false, object payload = null | ||||
|                                 , CancellationToken  cancellationToken = default) | ||||
|     { | ||||
|         Data              = data; | ||||
|         CancellationToken = cancellationToken; | ||||
|         CreatedTime       = createdTime; | ||||
|         IsConsumeOnce     = isConsumeOnce; | ||||
|         Payload           = payload; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public CancellationToken CancellationToken { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public DateTime CreatedTime { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public QueryVerifyCodeRsp Data { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string EventId => nameof(VerifyCodeCreatedEvent); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public bool IsConsumeOnce { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public object Payload { get; } | ||||
|     public VerifyCodeCreatedEvent(QueryVerifyCodeRsp payLoad) // | ||||
|         : base(payLoad) { } | ||||
| } | ||||
| @@ -4,7 +4,7 @@ | ||||
|         <ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/> | ||||
|     </ItemGroup> | ||||
|     <ItemGroup> | ||||
|         <PackageReference Include="CronExpressionDescriptor" Version="2.36.0"/> | ||||
|         <PackageReference Include="CronExpressionDescriptor" Version="2.38.0"/> | ||||
|         <PackageReference Include="Cronos" Version="0.9.0"/> | ||||
|         <PackageReference Include="NetAdmin.CsvHelper" Version="1.0.0"/> | ||||
|         <PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/> | ||||
|   | ||||
| @@ -133,7 +133,11 @@ public static class ServiceCollectionExtensions | ||||
|     /// </summary> | ||||
|     public static IServiceCollection AddEventBus(this IServiceCollection me) | ||||
|     { | ||||
|         return me.AddEventBus(builder => builder.AddSubscribers(App.Assemblies.ToArray())); | ||||
|         foreach (var type in App.EffectiveTypes.Where(x => typeof(IEventSubscriber).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract)) { | ||||
|             _ = me.AddSingleton(type); | ||||
|         } | ||||
|  | ||||
|         return me.AddSingleton<IEventPublisher>(new DefaultEventPublisher()); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -10,55 +10,50 @@ public sealed class SqlProfiler(ILogger<SqlProfiler> logger) : IEventSubscriber | ||||
|     /// <summary> | ||||
|     ///     Sql命令执行后 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(SqlCommandAfterEvent))] | ||||
|     public Task CommandAfterAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public Task CommandAfterAsync(SqlCommandAfterEvent @event) | ||||
|     { | ||||
|         var source = context.Source as SqlCommandAfterEvent; | ||||
|         logger.Info(source); | ||||
|         logger.Info(@event); | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Sql命令执行前 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(SqlCommandBeforeEvent))] | ||||
|     public Task CommandBeforeAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public Task CommandBeforeAsync(SqlCommandBeforeEvent @event) | ||||
|     { | ||||
|         var source = context.Source as SqlCommandBeforeEvent; | ||||
|         logger.Debug(source); | ||||
|         logger.Debug(@event); | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     种子数据插入完毕 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(SeedDataInsertedEvent))] | ||||
|     public Task SeedDataInsertedEventAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public Task SeedDataInsertedEventAsync(SeedDataInsertedEvent @event) | ||||
|     { | ||||
|         var source = context.Source as SeedDataInsertedEvent; | ||||
|         logger.Info(source); | ||||
|         logger.Info(@event); | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     同步数据库结构之后 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(SyncStructureAfterEvent))] | ||||
|     public Task SyncStructureAfterAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public Task SyncStructureAfterAsync(SyncStructureAfterEvent @event) | ||||
|     { | ||||
|         var source = context.Source as SyncStructureAfterEvent; | ||||
|         logger.Info(source); | ||||
|         logger.Info(@event); | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     同步数据库结构之前 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(SyncStructureBeforeEvent))] | ||||
|     public Task SyncStructureBeforeAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public Task SyncStructureBeforeAsync(SyncStructureBeforeEvent @event) | ||||
|     { | ||||
|         var source = context.Source as SyncStructureBeforeEvent; | ||||
|         logger.Info(source); | ||||
|         logger.Info(@event); | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| using System.Threading.Channels; | ||||
|  | ||||
| namespace NetAdmin.Infrastructure.EventBus; | ||||
|  | ||||
| /// <summary> | ||||
| ///     事件发布器默认实现 | ||||
| /// </summary> | ||||
| public sealed class DefaultEventPublisher : IEventPublisher | ||||
| { | ||||
|     private readonly Channel<object> _eventChannel; | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="DefaultEventPublisher" /> class. | ||||
|     /// </summary> | ||||
|     public DefaultEventPublisher() | ||||
|     { | ||||
|         _eventChannel = Channel.CreateUnbounded<object>(); | ||||
|         _ = new TaskFactory<Task>().StartNew( // | ||||
|             async state => { | ||||
|                 var subscribers = (List<MethodInfo>)state; | ||||
|                 await foreach (var msg in _eventChannel.Reader.ReadAllAsync()) { | ||||
|                     _ = Parallel.ForEach( // | ||||
|                         subscribers.Where(x => x.GetParameters().FirstOrDefault()?.ParameterType == msg.GetType()) | ||||
|                       , (x, _) => x.Invoke(App.GetService(x.DeclaringType), [msg])); | ||||
|                 } | ||||
|             }, App.EffectiveTypes.Where(x => typeof(IEventSubscriber).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract).SelectMany(x => x.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(y => y.IsDefined(typeof(EventSubscribeAttribute)))).ToList()); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task PublishAsync<T>(IEventData<T> eventData) | ||||
|     { | ||||
|         await _eventChannel.Writer.WriteAsync(eventData).ConfigureAwait(false); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,7 @@ | ||||
| namespace NetAdmin.Infrastructure.EventBus; | ||||
|  | ||||
| /// <summary> | ||||
| ///     事件处理程序特性 | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Method, Inherited = false)] | ||||
| public sealed class EventSubscribeAttribute : Attribute; | ||||
| @@ -0,0 +1,17 @@ | ||||
| namespace NetAdmin.Infrastructure.EventBus; | ||||
|  | ||||
| /// <summary> | ||||
| ///     事件数据接口 | ||||
| /// </summary> | ||||
| public interface IEventData<T> | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     事件发生时间 | ||||
|     /// </summary> | ||||
|     public DateTime CreatedTime { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     负载 | ||||
|     /// </summary> | ||||
|     public T PayLoad { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| namespace NetAdmin.Infrastructure.EventBus; | ||||
|  | ||||
| /// <summary> | ||||
| ///     事件发布器接口 | ||||
| /// </summary> | ||||
| public interface IEventPublisher | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     发布一条消息 | ||||
|     /// </summary> | ||||
|     Task PublishAsync<T>(IEventData<T> eventData); | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| namespace NetAdmin.Infrastructure.EventBus; | ||||
|  | ||||
| /// <summary> | ||||
| ///     事件订阅器接口 | ||||
| /// </summary> | ||||
| public interface IEventSubscriber; | ||||
| @@ -5,7 +5,7 @@ | ||||
|     <ItemGroup> | ||||
|         <PackageReference Include="NetAdmin.FreeSql.DbContext" Version="1.1.1" Label="refs"/> | ||||
|         <PackageReference Include="NetAdmin.FreeSql.Provider.Sqlite" Version="1.1.1" Label="refs"/> | ||||
|         <PackageReference Include="Gurion" Version="1.2.8" Label="refs"/> | ||||
|         <PackageReference Include="Gurion" Version="1.2.9" Label="refs"/> | ||||
|         <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0"/> | ||||
|         <PackageReference Include="Minio" Version="6.0.4"/> | ||||
|         <PackageReference Include="NSExt" Version="2.3.3"/> | ||||
|   | ||||
| @@ -10,11 +10,6 @@ public sealed class CaptchaService : ServiceBase<ICaptchaService>, ICaptchaServi | ||||
|     private static readonly Assembly _currAsm     = Assembly.GetAssembly(typeof(CaptchaService)); | ||||
|     private static readonly string   _currAsmName = _currAsm.FullName![.._currAsm.FullName.IndexOf(',')]; | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="CaptchaService" /> class. | ||||
|     /// </summary> | ||||
|     public CaptchaService() { } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<GetCaptchaRsp> GetCaptchaImageAsync() | ||||
|     { | ||||
|   | ||||
| @@ -10,8 +10,8 @@ public sealed class ApiSynchronizer(ILogger<ApiSynchronizer> logger) : IEventSub | ||||
|     /// <summary> | ||||
|     ///     同步Api接口 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(SyncStructureAfterEvent))] | ||||
|     public async Task SyncApiAsync(EventHandlerExecutingContext _) | ||||
|     [EventSubscribe] | ||||
|     public async Task SyncApiAsync(SyncStructureAfterEvent _) | ||||
|     { | ||||
|         var logService = App.GetService<IApiService>(); | ||||
|         await logService.SyncAsync().ConfigureAwait(false); | ||||
|   | ||||
| @@ -8,24 +8,16 @@ namespace NetAdmin.SysComponent.Host.Subscribers; | ||||
| /// </summary> | ||||
| public sealed class CacheCleaner : IEventSubscriber | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     Initializes a new instance of the <see cref="CacheCleaner" /> class. | ||||
|     /// </summary> | ||||
|     public CacheCleaner() { } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     用户缓存清理 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(UserUpdatedEvent))] | ||||
|     public Task RemoveUserInfoAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     #pragma warning disable CA1822 | ||||
|     public Task RemoveUserInfoAsync(UserUpdatedEvent @event) | ||||
|         #pragma warning restore CA1822 | ||||
|     { | ||||
|         if (context.Source is not UserUpdatedEvent userUpdatedEvent) { | ||||
|             return Task.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         var cache = App.GetService<IUserCache>(); | ||||
|         cache.Service.UserToken = ContextUserToken.Create(userUpdatedEvent.Data.Id, userUpdatedEvent.Data.Token, userUpdatedEvent.Data.UserName | ||||
|                                                         , userUpdatedEvent.Data.DeptId); | ||||
|         cache.Service.UserToken = ContextUserToken.Create(@event.PayLoad.Id, @event.PayLoad.Token, @event.PayLoad.UserName, @event.PayLoad.DeptId); | ||||
|         return cache.RemoveUserInfoAsync(); | ||||
|     } | ||||
| } | ||||
| @@ -12,18 +12,16 @@ public sealed class EmailCodeSender(ILogger<EmailCodeSender> logger) : IEventSub | ||||
|     /// <summary> | ||||
|     ///     发送邮件 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(VerifyCodeCreatedEvent))] | ||||
|     public async Task SendEmailAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public async Task SendEmailAsync(VerifyCodeCreatedEvent @event) | ||||
|     { | ||||
|         if (context.Source is not VerifyCodeCreatedEvent verifyCodeCreatedEvent || | ||||
|             verifyCodeCreatedEvent.Data.DeviceType != VerifyCodeDeviceTypes.Email) { | ||||
|         if (@event.PayLoad.DeviceType != VerifyCodeDeviceTypes.Email) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 发送... | ||||
|         var verifyCodeService = App.GetService<IVerifyCodeService>(); | ||||
|         _ = await verifyCodeService.SetVerifyCodeStatusAsync( | ||||
|                                        verifyCodeCreatedEvent.Data.Adapt<SetVerifyCodeStatusReq>() with { Status = VerifyCodeStatues.Sent }) | ||||
|         _ = await verifyCodeService.SetVerifyCodeStatusAsync(@event.PayLoad.Adapt<SetVerifyCodeStatusReq>() with { Status = VerifyCodeStatues.Sent }) | ||||
|                                    .ConfigureAwait(false); | ||||
|         logger.Info($"{nameof(IVerifyCodeService)}.{nameof(IVerifyCodeService.SetVerifyCodeStatusAsync)} {Ln.已处理完毕}"); | ||||
|     } | ||||
|   | ||||
| @@ -18,18 +18,16 @@ public sealed class OperationLogger : IEventSubscriber | ||||
|     /// <summary> | ||||
|     ///     保存请求日志到数据库 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(RequestLogEvent))] | ||||
|     public async Task OperationEventDbRecordAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     #pragma warning disable CA1822 | ||||
|     public async Task OperationEventDbRecordAsync(RequestLogEvent @event) | ||||
|         #pragma warning restore CA1822 | ||||
|     { | ||||
|         if (context.Source is not RequestLogEvent operationEvent) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (_requestLogs.Count > Numbers.REQUEST_LOG_BUFF_SIZE) { | ||||
|             await WriteToDbAsync().ConfigureAwait(false); | ||||
|         } | ||||
|         else { | ||||
|             _requestLogs.Enqueue(operationEvent.Data); | ||||
|             _requestLogs.Enqueue(@event.PayLoad); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -81,14 +79,12 @@ public sealed class OperationLogger : IEventSubscriber | ||||
|     /// <summary> | ||||
|     ///     保存请求日志到数据库 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(RequestLogEvent))] | ||||
|     public async Task OperationEventDbRecordAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     #pragma warning disable CA1822 | ||||
|     public async Task OperationEventDbRecordAsync(RequestLogEvent @event) | ||||
|         #pragma warning restore CA1822 | ||||
|     { | ||||
|         if (context.Source is not RequestLogEvent operationEvent) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         _ = await App.GetService<IRequestLogCache>().CreateAsync(operationEvent.Data).ConfigureAwait(false); | ||||
|         _ = await App.GetService<IRequestLogCache>().CreateAsync(@event.PayLoad).ConfigureAwait(false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| @@ -12,18 +12,16 @@ public sealed class SmsCodeSender(ILogger<SmsCodeSender> logger) : IEventSubscri | ||||
|     /// <summary> | ||||
|     ///     发送短信 | ||||
|     /// </summary> | ||||
|     [EventSubscribe(nameof(VerifyCodeCreatedEvent))] | ||||
|     public async Task SendSmsAsync(EventHandlerExecutingContext context) | ||||
|     [EventSubscribe] | ||||
|     public async Task SendSmsAsync(VerifyCodeCreatedEvent @event) | ||||
|     { | ||||
|         if (context.Source is not VerifyCodeCreatedEvent verifyCodeCreatedEvent || | ||||
|             verifyCodeCreatedEvent.Data.DeviceType != VerifyCodeDeviceTypes.Mobile) { | ||||
|         if (@event.PayLoad.DeviceType != VerifyCodeDeviceTypes.Mobile) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 发送... | ||||
|         var verifyCodeService = App.GetService<IVerifyCodeService>(); | ||||
|         _ = await verifyCodeService.SetVerifyCodeStatusAsync( | ||||
|                                        verifyCodeCreatedEvent.Data.Adapt<SetVerifyCodeStatusReq>() with { Status = VerifyCodeStatues.Sent }) | ||||
|         _ = await verifyCodeService.SetVerifyCodeStatusAsync(@event.PayLoad.Adapt<SetVerifyCodeStatusReq>() with { Status = VerifyCodeStatues.Sent }) | ||||
|                                    .ConfigureAwait(false); | ||||
|         logger.Info($"{nameof(IVerifyCodeService)}.{nameof(IVerifyCodeService.SetVerifyCodeStatusAsync)} {Ln.已处理完毕}"); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user