using LiveForum.IService.Messages; using LiveForum.Model.Events; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using StackExchange.Redis; using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace LiveForum.WebApi.BackgroundServices { /// /// 自定义消息后台消费者 /// 从 message:events:custom 队列消费自定义消息事件 /// public class CustomMessageConsumer : BackgroundService { private readonly IDatabase _database; private readonly IMessageEventHandler _eventHandler; private readonly ILogger _logger; private const string QUEUE_NAME = "message:events:custom"; public CustomMessageConsumer( IDatabase database, IMessageEventHandler eventHandler, ILogger logger) { _database = database; _eventHandler = eventHandler; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("[CustomConsumer] 自定义消息消费者已启动"); while (!stoppingToken.IsCancellationRequested) { try { // 从Redis List左侧弹出 var result = await _database.ListLeftPopAsync(QUEUE_NAME); if (result.HasValue) { var json = result.ToString(); // 反序列化事件 var evt = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); if (evt != null) { _logger.LogInformation( "[CustomConsumer] 开始处理自定义消息事件: EventId={EventId}, MessageType={MessageType}", evt.EventId, evt.MessageType); // 处理事件(带重试) await ProcessWithRetryAsync(evt, stoppingToken); } } else { // 队列为空,等待1秒再查询 await Task.Delay(1000, stoppingToken); } } catch (OperationCanceledException) { // 正常停止 break; } catch (Exception ex) { _logger.LogError(ex, "[CustomConsumer] 消费自定义消息事件时发生异常"); // 发生异常后等待5秒再继续 await Task.Delay(5000, stoppingToken); } } _logger.LogInformation("[CustomConsumer] 自定义消息消费者已停止"); } /// /// 带重试的事件处理 /// private async Task ProcessWithRetryAsync(CustomMessageEvent evt, CancellationToken stoppingToken) { const int maxRetries = 3; var retryCount = 0; while (retryCount < maxRetries && !stoppingToken.IsCancellationRequested) { try { await _eventHandler.HandleCustomMessageEventAsync(evt); _logger.LogInformation( "[CustomConsumer] 自定义消息事件处理成功: EventId={EventId}", evt.EventId); return; // 成功,退出重试循环 } catch (Exception ex) { retryCount++; if (retryCount >= maxRetries) { _logger.LogError(ex, "[CustomConsumer] 自定义消息事件处理失败(已重试{RetryCount}次): EventId={EventId}", retryCount, evt.EventId); // TODO: 可以将失败的事件写入死信队列或日志表 return; } _logger.LogWarning(ex, "[CustomConsumer] 自定义消息事件处理失败,准备重试({RetryCount}/{MaxRetries}): EventId={EventId}", retryCount, maxRetries, evt.EventId); // 延迟后重试(指数退避) await Task.Delay(1000 * retryCount, stoppingToken); } } } public override Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("[CustomConsumer] 正在停止自定义消息消费者..."); return base.StopAsync(cancellationToken); } } }