using Azure.Identity; using Core.Blueprint.DAL.Redis.Contracts; using Microsoft.Extensions.Logging; using StackExchange.Redis; using System.Text.Json; namespace Core.Blueprint.DAL.Redis { public class CacheService : ICacheService { private IDatabase _cacheDatabase = null!; private readonly ILogger _logger; public CacheService(string connectionString, ILogger logger) { _logger = logger; Task.Run(async () => { _cacheDatabase = await GetRedisDatabase(connectionString); }).Wait(); } private async Task GetRedisDatabase(string connectionString) { try { var configurationOptions = await ConfigurationOptions.Parse($"{connectionString}") .ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); configurationOptions.AbortOnConnectFail = false; var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions); _logger.LogInformation("Successfully connected to Redis."); return connectionMultiplexer.GetDatabase(); } catch (Exception ex) { _logger.LogError(ex, "Error establishing Redis connection."); throw; } } public async Task GetAsync(string key) { try { var value = await _cacheDatabase.StringGetAsync(key); if (value.IsNullOrEmpty) { _logger.LogInformation($"Cache miss for key: {key}"); return default; } _logger.LogInformation($"Cache hit for key: {key}"); return JsonSerializer.Deserialize(value); } catch (Exception ex) { _logger.LogError(ex, $"Error getting cache item with key {key}"); throw; } } public async Task SetAsync(string key, T value, TimeSpan? expiry = null) { try { var json = JsonSerializer.Serialize(value); await _cacheDatabase.StringSetAsync(key, json, expiry); _logger.LogInformation($"Cache item set with key: {key}"); } catch (Exception ex) { _logger.LogError(ex, $"Error setting cache item with key {key}"); throw; } } public async Task RemoveAsync(string key) { try { await _cacheDatabase.KeyDeleteAsync(key); _logger.LogInformation($"Cache item removed with key: {key}"); } catch (Exception ex) { _logger.LogError(ex, $"Error removing cache item with key {key}"); throw; } } public async Task ExistsAsync(string key) { try { var exists = await _cacheDatabase.KeyExistsAsync(key); _logger.LogInformation($"Cache item exists check for key: {key} - {exists}"); return exists; } catch (Exception ex) { _logger.LogError(ex, $"Error checking existence of cache item with key {key}"); throw; } } public async Task RefreshAsync(string key, TimeSpan? expiry = null) { try { var value = await _cacheDatabase.StringGetAsync(key); if (!value.IsNullOrEmpty) { await _cacheDatabase.StringSetAsync(key, value, expiry); _logger.LogInformation($"Cache item refreshed with key: {key}"); } else { _logger.LogWarning($"Cache item with key: {key} does not exist, cannot refresh"); } } catch (Exception ex) { _logger.LogError(ex, $"Error refreshing cache item with key {key}"); throw; } } } }