using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using SPMS.Application.Settings; using StackExchange.Redis; namespace SPMS.Infrastructure.Caching; public class RedisConnection : IAsyncDisposable { private readonly RedisSettings _settings; private readonly ILogger _logger; private readonly SemaphoreSlim _semaphore = new(1, 1); private ConnectionMultiplexer? _connection; public RedisConnection(IOptions settings, ILogger logger) { _settings = settings.Value; _logger = logger; } public async Task GetDatabaseAsync() { if (_connection is { IsConnected: true }) return _connection.GetDatabase(); await _semaphore.WaitAsync(); try { if (_connection is { IsConnected: true }) return _connection.GetDatabase(); _connection?.Dispose(); _logger.LogInformation("Redis 연결 시도: {ConnectionString}", MaskConnectionString(_settings.ConnectionString)); _connection = await ConnectionMultiplexer.ConnectAsync(_settings.ConnectionString); _logger.LogInformation("Redis 연결 성공"); return _connection.GetDatabase(); } catch (Exception ex) { _logger.LogError(ex, "Redis 연결 실패"); throw; } finally { _semaphore.Release(); } } private static string MaskConnectionString(string connectionString) { var parts = connectionString.Split(','); return parts.Length > 0 ? parts[0] + ",..." : connectionString; } public async ValueTask DisposeAsync() { if (_connection != null) { await _connection.CloseAsync(); _connection.Dispose(); } _semaphore.Dispose(); GC.SuppressFinalize(this); } }