From ff24c06934ae9471f7568a12d19db5c8754c7b51 Mon Sep 17 00:00:00 2001 From: Sergio Matias Date: Sat, 21 Jun 2025 22:05:27 -0600 Subject: [PATCH 1/3] Revert memory cache --- .../Adapters/CacheSettings.cs | 2 +- .../Configuration/RegisterBlueprint.cs | 35 +++----- ...acheProvider.cs => IRedisCacheProvider.cs} | 4 +- .../Core.Blueprint.Caching.csproj | 1 - .../Helpers/RedisCacheKeyHelper.cs | 8 +- Core.Blueprint.Redis/MemoryCacheProvider.cs | 86 ------------------- Core.Blueprint.Redis/RedisCacheProvider.cs | 26 ++---- 7 files changed, 27 insertions(+), 135 deletions(-) rename Core.Blueprint.Redis/Contracts/{ICacheProvider.cs => IRedisCacheProvider.cs} (96%) delete mode 100644 Core.Blueprint.Redis/MemoryCacheProvider.cs diff --git a/Core.Blueprint.Redis/Adapters/CacheSettings.cs b/Core.Blueprint.Redis/Adapters/CacheSettings.cs index 2be3840..128a89e 100644 --- a/Core.Blueprint.Redis/Adapters/CacheSettings.cs +++ b/Core.Blueprint.Redis/Adapters/CacheSettings.cs @@ -1,4 +1,4 @@ -namespace Core.Blueprint.Caching.Adapters +namespace Core.Blueprint.Redis { public interface ICacheSettings { diff --git a/Core.Blueprint.Redis/Configuration/RegisterBlueprint.cs b/Core.Blueprint.Redis/Configuration/RegisterBlueprint.cs index 854b173..3aeb596 100644 --- a/Core.Blueprint.Redis/Configuration/RegisterBlueprint.cs +++ b/Core.Blueprint.Redis/Configuration/RegisterBlueprint.cs @@ -1,10 +1,8 @@ -using Core.Blueprint.Caching.Adapters; -using Core.Blueprint.Caching.Contracts; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Core.Blueprint.Caching.Configuration +namespace Core.Blueprint.Redis.Configuration { /// /// Provides extension methods for registering Redis-related services in the DI container. @@ -19,30 +17,23 @@ namespace Core.Blueprint.Caching.Configuration /// The updated service collection. public static IServiceCollection AddRedis(this IServiceCollection services, IConfiguration configuration) { - // TODO for the following variable we'll need to add in the appsettings.json the following config: "UseRedisCache": true, - bool useRedis = configuration.GetValue("UseRedisCache"); - - if (useRedis) + // Retrieve the Redis connection string from the configuration. + // Get Redis configuration section + var redisConnectionString = configuration.GetSection("ConnectionStrings:Redis").Value; + if (string.IsNullOrEmpty(redisConnectionString)) { - var redisConnectionString = configuration.GetSection("ConnectionStrings:Redis").Value; - if (string.IsNullOrEmpty(redisConnectionString)) - { - throw new InvalidOperationException("Redis connection is not configured."); - } - - services.AddSingleton(provider => - new RedisCacheProvider(redisConnectionString, provider.GetRequiredService>())); - } - else - { - services.AddMemoryCache(); - services.AddSingleton(); + throw new InvalidOperationException("Redis connection is not configured."); } + // Register RedisCacheProvider + services.AddSingleton(provider => + new RedisCacheProvider(redisConnectionString, provider.GetRequiredService>())); + + // Get CacheSettings and register with the ICacheSettings interface var cacheSettings = configuration.GetSection("CacheSettings").Get(); if (cacheSettings == null) { - throw new InvalidOperationException("CacheSettings section is not configured."); + throw new InvalidOperationException("Redis CacheSettings section is not configured."); } services.AddSingleton(cacheSettings); diff --git a/Core.Blueprint.Redis/Contracts/ICacheProvider.cs b/Core.Blueprint.Redis/Contracts/IRedisCacheProvider.cs similarity index 96% rename from Core.Blueprint.Redis/Contracts/ICacheProvider.cs rename to Core.Blueprint.Redis/Contracts/IRedisCacheProvider.cs index cf0a323..f9a7b5e 100644 --- a/Core.Blueprint.Redis/Contracts/ICacheProvider.cs +++ b/Core.Blueprint.Redis/Contracts/IRedisCacheProvider.cs @@ -1,9 +1,9 @@ -namespace Core.Blueprint.Caching.Contracts +namespace Core.Blueprint.Redis { /// /// Interface for managing Redis cache operations. /// - public interface ICacheProvider + public interface IRedisCacheProvider { /// /// Retrieves a cache item by its key. diff --git a/Core.Blueprint.Redis/Core.Blueprint.Caching.csproj b/Core.Blueprint.Redis/Core.Blueprint.Caching.csproj index 8109d2c..bcfc356 100644 --- a/Core.Blueprint.Redis/Core.Blueprint.Caching.csproj +++ b/Core.Blueprint.Redis/Core.Blueprint.Caching.csproj @@ -9,7 +9,6 @@ - diff --git a/Core.Blueprint.Redis/Helpers/RedisCacheKeyHelper.cs b/Core.Blueprint.Redis/Helpers/RedisCacheKeyHelper.cs index 6d9e374..f7f53cb 100644 --- a/Core.Blueprint.Redis/Helpers/RedisCacheKeyHelper.cs +++ b/Core.Blueprint.Redis/Helpers/RedisCacheKeyHelper.cs @@ -1,7 +1,11 @@ -using System.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; -namespace Core.Blueprint.Caching.Helpers +namespace Core.Blueprint.Redis.Helpers { /// /// Helper class for generating consistent and normalized cache keys. diff --git a/Core.Blueprint.Redis/MemoryCacheProvider.cs b/Core.Blueprint.Redis/MemoryCacheProvider.cs deleted file mode 100644 index 91beb2a..0000000 --- a/Core.Blueprint.Redis/MemoryCacheProvider.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Core.Blueprint.Caching.Contracts; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Caching.Memory; -using System.Text.Json; - -namespace Core.Blueprint.Caching -{ - public sealed class MemoryCacheProvider : ICacheProvider - { - private readonly IMemoryCache _cache; - private readonly ILogger _logger; - public MemoryCacheProvider(IMemoryCache cache, ILogger logger) - { - _cache = cache; - _logger = logger; - } - - public ValueTask GetAsync(string key) - { - if (_cache.TryGetValue(key, out var value)) - { - if (value is TEntity typedValue) - { - return ValueTask.FromResult(typedValue); - } - - try - { - var json = value?.ToString(); - var deserialized = JsonSerializer.Deserialize(json); - return ValueTask.FromResult(deserialized); - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Error deserializing cache value for key {Key}", key); - } - } - - return ValueTask.FromResult(default(TEntity)); - } - - public ValueTask SetAsync(string key, TEntity value, TimeSpan? expiry = null) - { - var options = new MemoryCacheEntryOptions(); - if (expiry.HasValue) - { - options.SetAbsoluteExpiration(expiry.Value); - } - - _cache.Set(key, value, options); - return ValueTask.CompletedTask; - } - - public ValueTask RemoveAsync(string key) - { - _cache.Remove(key); - return ValueTask.CompletedTask; - } - - public ValueTask ExistsAsync(string key) - { - return ValueTask.FromResult(_cache.TryGetValue(key, out _)); - } - - public ValueTask RefreshAsync(string key, TimeSpan? expiry = null) - { - // MemoryCache does not support sliding expiration refresh like Redis, - // so we must re-set the value manually if required. - - if (_cache.TryGetValue(key, out var value)) - { - _cache.Remove(key); - - var options = new MemoryCacheEntryOptions(); - if (expiry.HasValue) - { - options.SetAbsoluteExpiration(expiry.Value); - } - - _cache.Set(key, value, options); - } - - return ValueTask.CompletedTask; - } - } -} diff --git a/Core.Blueprint.Redis/RedisCacheProvider.cs b/Core.Blueprint.Redis/RedisCacheProvider.cs index 90901ce..525e310 100644 --- a/Core.Blueprint.Redis/RedisCacheProvider.cs +++ b/Core.Blueprint.Redis/RedisCacheProvider.cs @@ -1,15 +1,14 @@ using Azure.Identity; -using Core.Blueprint.Caching.Contracts; using Microsoft.Extensions.Logging; using StackExchange.Redis; using System.Text.Json; -namespace Core.Blueprint.Caching +namespace Core.Blueprint.Redis { /// /// Redis cache provider for managing cache operations. /// - public sealed class RedisCacheProvider : ICacheProvider + public sealed class RedisCacheProvider : IRedisCacheProvider { private IDatabase _cacheDatabase = null!; private readonly ILogger _logger; @@ -35,29 +34,14 @@ namespace Core.Blueprint.Caching /// The Redis connection string. /// An instance representing the Redis cache database. /// Thrown when the connection to Redis fails. InitializeRedisAsync(string connectionString) + async Task InitializeRedisAsync(string connectionString) { try { - var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; - - ConfigurationOptions configurationOptions; - - if (environment.Equals("Local", StringComparison.OrdinalIgnoreCase)) - { - // Use simple local Redis config - configurationOptions = ConfigurationOptions.Parse(connectionString); - } - else - { - // Use Azure Redis config - configurationOptions = await ConfigurationOptions - .Parse(connectionString) - .ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); - } + var configurationOptions = await ConfigurationOptions.Parse($"{connectionString}") + .ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); configurationOptions.AbortOnConnectFail = false; - var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions); _logger.LogInformation("Successfully connected to Redis."); From 7b326051bbb4d9c27e163b0fa81f70cc16e0befe Mon Sep 17 00:00:00 2001 From: Sergio Matias Date: Sat, 21 Jun 2025 22:12:20 -0600 Subject: [PATCH 2/3] Upgrade redis package --- Core.BluePrint.Packages.sln | 2 +- ...ore.Blueprint.Caching.csproj => Core.Blueprint.Redis.csproj} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Core.Blueprint.Redis/{Core.Blueprint.Caching.csproj => Core.Blueprint.Redis.csproj} (100%) diff --git a/Core.BluePrint.Packages.sln b/Core.BluePrint.Packages.sln index 0c6eb67..7a136ec 100644 --- a/Core.BluePrint.Packages.sln +++ b/Core.BluePrint.Packages.sln @@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.KeyVault", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Blueprint.Mongo", "Core.Blueprint.Mongo\Core.Blueprint.Mongo.csproj", "{27A8E3E1-D613-4D5B-8105-485699409F1E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Blueprint.Caching", "Core.Blueprint.Redis\Core.Blueprint.Caching.csproj", "{11F2AA11-FB98-4A33-AEE4-CD49588D2FE1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Blueprint.Redis", "Core.Blueprint.Redis\Core.Blueprint.Redis.csproj", "{11F2AA11-FB98-4A33-AEE4-CD49588D2FE1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Blueprint.Storage", "Core.Blueprint.Storage\Core.Blueprint.Storage.csproj", "{636E4520-79F9-46C8-990D-08F2D24A151C}" EndProject diff --git a/Core.Blueprint.Redis/Core.Blueprint.Caching.csproj b/Core.Blueprint.Redis/Core.Blueprint.Redis.csproj similarity index 100% rename from Core.Blueprint.Redis/Core.Blueprint.Caching.csproj rename to Core.Blueprint.Redis/Core.Blueprint.Redis.csproj From 73b909f780d9436ad85f0c731169874629540503 Mon Sep 17 00:00:00 2001 From: Sergio Matias Date: Sun, 22 Jun 2025 01:28:14 -0600 Subject: [PATCH 3/3] Avoid chained credential for local environment in sql package --- .../Configuration/RegisterBlueprint.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core.Blueprint.SQLServer/Configuration/RegisterBlueprint.cs b/Core.Blueprint.SQLServer/Configuration/RegisterBlueprint.cs index 76d6af6..53d36a6 100644 --- a/Core.Blueprint.SQLServer/Configuration/RegisterBlueprint.cs +++ b/Core.Blueprint.SQLServer/Configuration/RegisterBlueprint.cs @@ -18,12 +18,17 @@ namespace Core.Blueprint.SQLServer.Configuration /// An updated with SQL Server services registered. public static IServiceCollection AddSQLServer(this IServiceCollection services, IConfiguration configuration) { - var chainedCredentials = new ChainedTokenCredential( + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; + + if (environment != "Local") + { + var chainedCredentials = new ChainedTokenCredential( new ManagedIdentityCredential(), new SharedTokenCacheCredential(), new VisualStudioCredential(), new VisualStudioCodeCredential() ); + } services.AddScoped(typeof(IEntityRepository<,>), typeof(EntityRepository<,>));