fix: 租户端启动补齐字典与消息依赖

This commit is contained in:
root
2026-01-30 02:42:22 +00:00
parent f1963ae1a5
commit 8e315e4f17
5 changed files with 82 additions and 3 deletions

View File

@@ -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<string>("Endpoint");

View File

@@ -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;
/// <summary>
/// 身份模块操作日志发布器(基于 MassTransit Outbox
/// </summary>
public sealed class IdentityOperationLogPublisher(IPublishEndpoint publishEndpoint) : IIdentityOperationLogPublisher
public sealed class IdentityOperationLogPublisher(
ILogger<IdentityOperationLogPublisher> logger,
IPublishEndpoint? publishEndpoint = null) : IIdentityOperationLogPublisher
{
/// <inheritdoc />
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);
}
}

View File

@@ -17,8 +17,17 @@ public static class MessagingServiceCollectionExtensions
/// </summary>
public static IServiceCollection AddMessagingModule(this IServiceCollection services, IConfiguration configuration)
{
var rabbitMqSection = configuration.GetSection("RabbitMQ");
if (!rabbitMqSection.Exists())
{
services.AddSingleton<IMessagePublisher, NoOpMessagePublisher>();
services.AddSingleton<IMessageSubscriber, NoOpMessageSubscriber>();
return services;
}
// 1. (空行后) 存在 RabbitMQ 配置时才启用真实 MQ 能力(启动时验证配置完整性)
services.AddOptions<RabbitMqOptions>()
.Bind(configuration.GetSection("RabbitMQ"))
.Bind(rabbitMqSection)
.ValidateDataAnnotations()
.ValidateOnStart();

View File

@@ -0,0 +1,21 @@
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Module.Messaging.Abstractions;
namespace TakeoutSaaS.Module.Messaging.Services;
/// <summary>
/// 空实现消息发布器:用于未配置 RabbitMQ 的开发/测试场景,避免启动依赖外部 MQ。
/// </summary>
public sealed class NoOpMessagePublisher(ILogger<NoOpMessagePublisher> logger) : IMessagePublisher
{
/// <inheritdoc />
public Task PublishAsync<T>(string routingKey, T message, CancellationToken cancellationToken = default)
{
logger.LogDebug(
"未配置 RabbitMQ已跳过消息发布RoutingKey={RoutingKey} MessageType={MessageType}",
routingKey,
typeof(T).FullName ?? typeof(T).Name);
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,25 @@
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Module.Messaging.Abstractions;
namespace TakeoutSaaS.Module.Messaging.Services;
/// <summary>
/// 空实现消息订阅器:用于未配置 RabbitMQ 的开发/测试场景。
/// </summary>
public sealed class NoOpMessageSubscriber(ILogger<NoOpMessageSubscriber> logger) : IMessageSubscriber
{
/// <inheritdoc />
public Task SubscribeAsync<T>(string queue, string routingKey, Func<T, CancellationToken, Task<bool>> handler, CancellationToken cancellationToken = default)
{
logger.LogWarning("未配置 RabbitMQ消息订阅被禁用Queue={Queue} RoutingKey={RoutingKey}", queue, routingKey);
return Task.CompletedTask;
}
// 1. (空行后) 释放资源NoOp 实现无实际资源)
/// <inheritdoc />
public ValueTask DisposeAsync()
{
logger.LogDebug("NoOpMessageSubscriber 已释放。");
return ValueTask.CompletedTask;
}
}