From 2cfbd0706f0e9797b9f77c036b6cb3e601303eaf Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sat, 10 Jan 2026 21:24:18 +0700 Subject: [PATCH] feat(docs): Add Redis Cache integration details to Vietnamese documentation - Updated README.md to include Redis Cache integration as a new feature. - Enhanced DependencyInjection.cs to register Redis Cache services and connection settings. - Improved clarity in Vietnamese documentation regarding Clean Architecture principles. --- services/_template_dot_net/README.md | 3 +- .../Common/Interfaces/ICacheService.cs | 8 ++++ .../DependencyInjection.cs | 18 +++++++++ .../Services/RedisCacheService.cs | 40 +++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 services/_template_dot_net/src/YourServiceName.Domain/Common/Interfaces/ICacheService.cs create mode 100644 services/_template_dot_net/src/YourServiceName.Infrastructure/Services/RedisCacheService.cs diff --git a/services/_template_dot_net/README.md b/services/_template_dot_net/README.md index 98f32bec..f58697b4 100644 --- a/services/_template_dot_net/README.md +++ b/services/_template_dot_net/README.md @@ -17,7 +17,8 @@ - ASP.NET Core 10 Web API - Entity Framework Core 10 (PostgreSQL / Neon) - **Neon Database Integration** (Connection Resilience) -- 原 tắc Clean Architecture +- **Redis Cache** (StackExchange.Redis) +- Nguyên tắc Clean Architecture - **CQRS với MediatR** - **Resilience với Polly** - **Global Exception Handling (RFC 7807)** diff --git a/services/_template_dot_net/src/YourServiceName.Domain/Common/Interfaces/ICacheService.cs b/services/_template_dot_net/src/YourServiceName.Domain/Common/Interfaces/ICacheService.cs new file mode 100644 index 00000000..38724217 --- /dev/null +++ b/services/_template_dot_net/src/YourServiceName.Domain/Common/Interfaces/ICacheService.cs @@ -0,0 +1,8 @@ +namespace YourServiceName.Domain.Common.Interfaces; + +public interface ICacheService +{ + Task GetAsync(string key, CancellationToken cancellationToken = default); + Task SetAsync(string key, T value, TimeSpan? expiration = null, CancellationToken cancellationToken = default); + Task RemoveAsync(string key, CancellationToken cancellationToken = default); +} diff --git a/services/_template_dot_net/src/YourServiceName.Infrastructure/DependencyInjection.cs b/services/_template_dot_net/src/YourServiceName.Infrastructure/DependencyInjection.cs index 08ed5362..f96c401c 100644 --- a/services/_template_dot_net/src/YourServiceName.Infrastructure/DependencyInjection.cs +++ b/services/_template_dot_net/src/YourServiceName.Infrastructure/DependencyInjection.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using YourServiceName.Infrastructure.Data.Interceptors; using YourServiceName.Domain.SeedWork; +using StackExchange.Redis; +using YourServiceName.Domain.Common.Interfaces; namespace YourServiceName.Infrastructure; @@ -30,6 +32,22 @@ public static class DependencyInjection services.AddScoped(provider => provider.GetRequiredService()); + // EN: Register Redis Cache + // VI: Đăng ký Redis Cache + services.AddSingleton(sp => + { + var configuration = sp.GetRequiredService(); + var connectionString = configuration.GetSection("Redis:ConnectionString").Value; + var instanceName = configuration.GetSection("Redis:InstanceName").Value; + + var options = ConfigurationOptions.Parse(connectionString); + // options.ChannelPrefix = instanceName; // Optional prefix + + return ConnectionMultiplexer.Connect(options); + }); + + services.AddScoped(); + return services; } } diff --git a/services/_template_dot_net/src/YourServiceName.Infrastructure/Services/RedisCacheService.cs b/services/_template_dot_net/src/YourServiceName.Infrastructure/Services/RedisCacheService.cs new file mode 100644 index 00000000..edbc9a2d --- /dev/null +++ b/services/_template_dot_net/src/YourServiceName.Infrastructure/Services/RedisCacheService.cs @@ -0,0 +1,40 @@ +using System.Text.Json; +using Microsoft.Extensions.Configuration; +using StackExchange.Redis; +using YourServiceName.Domain.Common.Interfaces; + +namespace YourServiceName.Infrastructure.Services; + +public class RedisCacheService : ICacheService +{ + private readonly IConnectionMultiplexer _connectionMultiplexer; + private readonly IDatabase _database; + + public RedisCacheService(IConnectionMultiplexer connectionMultiplexer) + { + _connectionMultiplexer = connectionMultiplexer; + _database = _connectionMultiplexer.GetDatabase(); + } + + public async Task GetAsync(string key, CancellationToken cancellationToken = default) + { + var value = await _database.StringGetAsync(key); + if (value.IsNullOrEmpty) + { + return default; + } + + return JsonSerializer.Deserialize(value); + } + + public async Task SetAsync(string key, T value, TimeSpan? expiration = null, CancellationToken cancellationToken = default) + { + var json = JsonSerializer.Serialize(value); + await _database.StringSetAsync(key, json, expiration); + } + + public async Task RemoveAsync(string key, CancellationToken cancellationToken = default) + { + await _database.KeyDeleteAsync(key); + } +}