using LiveForum.Code.Redis.Contract; using LiveForum.IService.Messages; using LiveForum.Model.Events; using Microsoft.Extensions.Logging; using StackExchange.Redis; using System; using System.Text.Json; using System.Threading.Tasks; namespace LiveForum.Service.Messages { /// /// 基于Redis的消息事件总线实现 /// public class RedisMessageEventBus : IMessageEventBus { private readonly IRedisService _redisService; private readonly ILogger _logger; private readonly IDatabase _database; // 队列名称常量 private const string LIKE_QUEUE = "message:events:like"; private const string COMMENT_QUEUE = "message:events:comment"; private const string CUSTOM_QUEUE = "message:events:custom"; public RedisMessageEventBus( IRedisService redisService, ILogger logger, IDatabase database) { _redisService = redisService; _logger = logger; _database = database; } /// /// 发布消息事件到Redis队列 /// public async Task PublishAsync(T eventData) where T : MessageEventBase { try { // 根据事件类型选择队列 var queueName = GetQueueName(eventData); // 序列化事件数据 var json = JsonSerializer.Serialize(eventData, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); // 推入Redis List队列(右侧推入,左侧弹出,保证FIFO) await _database.ListRightPushAsync(queueName, json); _logger.LogInformation( "[EventBus] 事件已发布: {EventType}, EventId: {EventId}, Queue: {Queue}", eventData.EventType, eventData.EventId, queueName); } catch (Exception ex) { _logger.LogError(ex, "[EventBus] 发布事件失败: {EventType}, EventId: {EventId}", eventData.EventType, eventData.EventId); // 发布失败不应该阻塞主业务流程,只记录日志 // 但也可以选择抛出异常让调用方处理 throw; } } /// /// 获取队列长度 /// public async Task GetQueueLengthAsync(string queueName) { try { return await _database.ListLengthAsync(queueName); } catch (Exception ex) { _logger.LogError(ex, "[EventBus] 获取队列长度失败: {Queue}", queueName); return -1; } } /// /// 根据事件类型获取队列名称 /// private string GetQueueName(MessageEventBase eventData) { return eventData switch { LikeEvent => LIKE_QUEUE, CommentReplyEvent => COMMENT_QUEUE, CustomMessageEvent => CUSTOM_QUEUE, _ => throw new ArgumentException($"未知的事件类型: {eventData.GetType().Name}") }; } } }