From 8e315e4f17d14a01858d78efa22764a0389c467e Mon Sep 17 00:00:00 2001 From: root Date: Fri, 30 Jan 2026 02:42:22 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A7=9F=E6=88=B7=E7=AB=AF=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E8=A1=A5=E9=BD=90=E5=AD=97=E5=85=B8=E4=B8=8E=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Api/TakeoutSaaS.TenantApi/Program.cs | 12 +++++++++ .../IdentityOperationLogPublisher.cs | 16 ++++++++++-- .../MessagingServiceCollectionExtensions.cs | 11 +++++++- .../Services/NoOpMessagePublisher.cs | 21 ++++++++++++++++ .../Services/NoOpMessageSubscriber.cs | 25 +++++++++++++++++++ 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs create mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs diff --git a/src/Api/TakeoutSaaS.TenantApi/Program.cs b/src/Api/TakeoutSaaS.TenantApi/Program.cs index 128d909..b20bcb6 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Program.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Program.cs @@ -11,10 +11,14 @@ using OpenTelemetry.Resources; using OpenTelemetry.Trace; using Serilog; using TakeoutSaaS.Application.App.Extensions; +using TakeoutSaaS.Application.Dictionary.Extensions; using TakeoutSaaS.Application.Identity.Extensions; +using TakeoutSaaS.Application.Messaging.Extensions; using TakeoutSaaS.Infrastructure.App.Extensions; +using TakeoutSaaS.Infrastructure.Dictionary.Extensions; using TakeoutSaaS.Infrastructure.Identity.Extensions; using TakeoutSaaS.Module.Authorization.Extensions; +using TakeoutSaaS.Module.Messaging.Extensions; using TakeoutSaaS.Module.Tenancy.Extensions; using TakeoutSaaS.Shared.Web.Extensions; using TakeoutSaaS.Shared.Web.Swagger; @@ -94,6 +98,14 @@ builder.Services.AddIdentityApplication(enableMiniSupport: false); builder.Services.AddAppInfrastructure(builder.Configuration); builder.Services.AddIdentityInfrastructure(builder.Configuration, enableMiniFeatures: false, enableAdminSeed: false); +// 6. (空行后) 注册字典模块(系统参数、字典项、缓存等) +builder.Services.AddDictionaryApplication(); +builder.Services.AddDictionaryInfrastructure(builder.Configuration); + +// 6. (空行后) 注册消息发布能力(未配置 RabbitMQ 时自动降级为 NoOp 实现) +builder.Services.AddMessagingApplication(); +builder.Services.AddMessagingModule(builder.Configuration); + // 7. 配置 OpenTelemetry 采集 var otelSection = builder.Configuration.GetSection("Otel"); var otelEndpoint = otelSection.GetValue("Endpoint"); diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs index a88055d..918f5a9 100644 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs @@ -1,4 +1,5 @@ using MassTransit; +using Microsoft.Extensions.Logging; using TakeoutSaaS.Application.Identity.Abstractions; using TakeoutSaaS.Application.Identity.Events; @@ -7,9 +8,20 @@ namespace TakeoutSaaS.Infrastructure.Logs.Publishers; /// /// 身份模块操作日志发布器(基于 MassTransit Outbox)。 /// -public sealed class IdentityOperationLogPublisher(IPublishEndpoint publishEndpoint) : IIdentityOperationLogPublisher +public sealed class IdentityOperationLogPublisher( + ILogger logger, + IPublishEndpoint? publishEndpoint = null) : IIdentityOperationLogPublisher { /// public Task PublishAsync(IdentityUserOperationLogMessage message, CancellationToken cancellationToken = default) - => publishEndpoint.Publish(message, cancellationToken); + { + if (publishEndpoint is null) + { + logger.LogDebug("未配置 MassTransit,已跳过操作日志消息发布:{OperationType}", message.OperationType); + return Task.CompletedTask; + } + + // 1. (空行后) 已配置 MassTransit 时正常发布消息 + return publishEndpoint.Publish(message, cancellationToken); + } } diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs index 9a53b1a..f1f7081 100644 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs +++ b/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs @@ -17,8 +17,17 @@ public static class MessagingServiceCollectionExtensions /// public static IServiceCollection AddMessagingModule(this IServiceCollection services, IConfiguration configuration) { + var rabbitMqSection = configuration.GetSection("RabbitMQ"); + if (!rabbitMqSection.Exists()) + { + services.AddSingleton(); + services.AddSingleton(); + return services; + } + + // 1. (空行后) 存在 RabbitMQ 配置时才启用真实 MQ 能力(启动时验证配置完整性) services.AddOptions() - .Bind(configuration.GetSection("RabbitMQ")) + .Bind(rabbitMqSection) .ValidateDataAnnotations() .ValidateOnStart(); diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs new file mode 100644 index 0000000..3d139e0 --- /dev/null +++ b/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Logging; +using TakeoutSaaS.Module.Messaging.Abstractions; + +namespace TakeoutSaaS.Module.Messaging.Services; + +/// +/// 空实现消息发布器:用于未配置 RabbitMQ 的开发/测试场景,避免启动依赖外部 MQ。 +/// +public sealed class NoOpMessagePublisher(ILogger logger) : IMessagePublisher +{ + /// + public Task PublishAsync(string routingKey, T message, CancellationToken cancellationToken = default) + { + logger.LogDebug( + "未配置 RabbitMQ,已跳过消息发布:RoutingKey={RoutingKey} MessageType={MessageType}", + routingKey, + typeof(T).FullName ?? typeof(T).Name); + return Task.CompletedTask; + } +} + diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs new file mode 100644 index 0000000..5cfc432 --- /dev/null +++ b/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; +using TakeoutSaaS.Module.Messaging.Abstractions; + +namespace TakeoutSaaS.Module.Messaging.Services; + +/// +/// 空实现消息订阅器:用于未配置 RabbitMQ 的开发/测试场景。 +/// +public sealed class NoOpMessageSubscriber(ILogger logger) : IMessageSubscriber +{ + /// + public Task SubscribeAsync(string queue, string routingKey, Func> handler, CancellationToken cancellationToken = default) + { + logger.LogWarning("未配置 RabbitMQ,消息订阅被禁用:Queue={Queue} RoutingKey={RoutingKey}", queue, routingKey); + return Task.CompletedTask; + } + + // 1. (空行后) 释放资源(NoOp 实现无实际资源) + /// + public ValueTask DisposeAsync() + { + logger.LogDebug("NoOpMessageSubscriber 已释放。"); + return ValueTask.CompletedTask; + } +}