using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using RabbitMQ.Client; using SPMS.Application.Settings; namespace SPMS.Infrastructure.Messaging; public class RabbitMQInitializer : BackgroundService { private readonly RabbitMQConnection _connection; private readonly RabbitMQSettings _settings; private readonly ILogger _logger; private static readonly TimeSpan RetryInterval = TimeSpan.FromSeconds(30); public bool IsInitialized { get; private set; } public RabbitMQInitializer( RabbitMQConnection connection, IOptions settings, ILogger logger) { _connection = connection; _settings = settings.Value; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { try { await InitializeAsync(stoppingToken); IsInitialized = true; _logger.LogInformation("RabbitMQ 초기화 완료"); return; } catch (Exception ex) { _logger.LogWarning(ex, "RabbitMQ 초기화 실패 — {RetrySeconds}초 후 재시도합니다.", RetryInterval.TotalSeconds); await Task.Delay(RetryInterval, stoppingToken); } } } private async Task InitializeAsync(CancellationToken cancellationToken) { await using var channel = await _connection.CreateChannelAsync(cancellationToken); await channel.ExchangeDeclareAsync( exchange: _settings.Exchange, type: ExchangeType.Direct, durable: true, autoDelete: false, arguments: null, cancellationToken: cancellationToken); _logger.LogInformation("Exchange 선언 완료: {Exchange}", _settings.Exchange); var queueArgs = new Dictionary { { "x-message-ttl", _settings.MessageTtl } }; await channel.QueueDeclareAsync( queue: _settings.PushQueue, durable: true, exclusive: false, autoDelete: false, arguments: queueArgs, cancellationToken: cancellationToken); await channel.QueueBindAsync( queue: _settings.PushQueue, exchange: _settings.Exchange, routingKey: "push", cancellationToken: cancellationToken); _logger.LogInformation("Queue 선언 및 바인딩 완료: {Queue} → {Exchange} (routing_key: push)", _settings.PushQueue, _settings.Exchange); await channel.QueueDeclareAsync( queue: _settings.ScheduleQueue, durable: true, exclusive: false, autoDelete: false, arguments: queueArgs, cancellationToken: cancellationToken); await channel.QueueBindAsync( queue: _settings.ScheduleQueue, exchange: _settings.Exchange, routingKey: "schedule", cancellationToken: cancellationToken); _logger.LogInformation("Queue 선언 및 바인딩 완료: {Queue} → {Exchange} (routing_key: schedule)", _settings.ScheduleQueue, _settings.Exchange); } }