FGutierrez.Core.DistributedCache
1.1.6
dotnet add package FGutierrez.Core.DistributedCache --version 1.1.6
NuGet\Install-Package FGutierrez.Core.DistributedCache -Version 1.1.6
<PackageReference Include="FGutierrez.Core.DistributedCache" Version="1.1.6" />
<PackageVersion Include="FGutierrez.Core.DistributedCache" Version="1.1.6" />
<PackageReference Include="FGutierrez.Core.DistributedCache" />
paket add FGutierrez.Core.DistributedCache --version 1.1.6
#r "nuget: FGutierrez.Core.DistributedCache, 1.1.6"
#:package FGutierrez.Core.DistributedCache@1.1.6
#addin nuget:?package=FGutierrez.Core.DistributedCache&version=1.1.6
#tool nuget:?package=FGutierrez.Core.DistributedCache&version=1.1.6
β‘ FGutierrez.Core.DistributedCache
π Overview
FGutierrez.Core.DistributedCache is a high-performance distributed caching library for .NET 8 designed to provide a unified abstraction over multiple cache providers.
The library simplifies cache integration by providing:
- In-memory caching
- Redis distributed caching
- Automatic resilience and fallback strategies
- HTTP response caching middleware
- OpenTelemetry metrics
- Health checks
- Provider-based extensibility
- Declarative method-level caching
Built following cloud-native architecture principles, applications can consume caching capabilities without being coupled to a specific infrastructure provider.
β¨ Features
| Feature | Description |
|---|---|
| π§© Unified API | Single abstraction over multiple cache providers |
| β‘ High Performance | Optimized cache access patterns |
| π Resilience | Automatic fallback when distributed cache is unavailable |
| π§ Cache Aside Pattern | Built-in GetOrAddAsync workflow |
| π HTTP Middleware | API response caching support |
| π Observability | OpenTelemetry metrics integration |
| π©Ί Health Checks | Provider availability monitoring |
| π·οΈ Declarative Caching | Attribute-based caching using [Cacheable] |
ποΈ Architecture
The library follows a provider-based architecture where the application consumes a single abstraction while the infrastructure layer decides the cache implementation.
graph TD
App[Application] --> Cache[ICoreCacheService]
Cache --> Decorator[Resilient Cache Decorator]
Decorator --> Redis[RedisCacheStorage]
Decorator --> Memory[MemoryCacheStorage]
Redis --> RedisServer[(Redis Server)]
Memory --> Runtime[(Application Memory)]
π Cache Provider Factory
When an application requires explicit provider selection, the library exposes ICacheServiceFactory.
sequenceDiagram
participant C as Client (Repository)
participant F as ICacheServiceFactory
participant DI as IServiceProvider
participant D as ResilientCacheDecorator
participant R as RedisCacheStorage
participant M as MemoryCacheStorage
C->>F: GetCacheService(ProviderType)
F->>DI: Resolve(ICoreCacheService)
Note over DI: Configuration injects the<br/>ResilientCacheDecorator by default
DI-->>F: Returns ResilientCacheDecorator
F-->>C: Returns ICoreCacheService
C->>D: GetAsync(key)
alt Redis is Healthy
D->>R: Execute operation
R-->>D: Return value
else Redis is unavailable
Note over D: Apply fallback strategy
D->>M: Execute operation
M-->>D: Return value
end
D-->>C: Return final result
π‘οΈ Resilience Strategy
The default implementation uses a resilient decorator that automatically falls back to memory cache when Redis becomes unavailable.
flowchart TD
Request([Cache Request])
Request --> RedisCheck{Redis Available?}
RedisCheck -- Yes --> RedisAccess[Attempt Redis Access]
RedisAccess --> Success{Operation Successful?}
Success -- Yes --> Return([Return Cached Data])
Success -- No --> Fallback[Log Error + Memory Fallback]
RedisCheck -- No --> Fallback
Fallback --> MemoryAccess[Query Memory Cache]
MemoryAccess --> Return
β‘ Cache Aside Pattern
The library provides a built-in GetOrAddAsync workflow.
sequenceDiagram
participant App as Application
participant Cache as ICoreCacheService
participant DB as Data Source
App->>Cache: GetOrAddAsync(key, factory)
Cache->>Cache: Check cache entry
alt Cache Hit
Cache-->>App: Return cached value
else Cache Miss
Cache->>DB: Execute factory()
DB-->>Cache: Return data
Cache->>Cache: Store value
Cache-->>App: Return new value
end
π HTTP Cache Middleware
Provides transparent response caching capabilities for API endpoints.
sequenceDiagram
participant Client as HTTP Client
participant MW as Cache Middleware
participant API as API Endpoint
Client->>MW: GET /api/resource
MW->>MW: Check cache
alt Cache Hit
MW-->>Client: Cached Response
else Cache Miss
MW->>API: Execute Request
API-->>MW: Response
MW->>MW: Store Response
MW-->>Client: Original Response
end
π¦ Installation
Install the package using NuGet:
dotnet add package FGutierrez.Core.DistributedCache
βοΈ Configuration
appsettings.json
{
"DistributedCache": {
"Provider": "Redis",
"InstanceName": "MySystem",
"Redis": {
"Enabled": true,
"Host": "localhost:6379",
"Password": "your-password"
}
}
}
Redis Setup
var builder = WebApplication.CreateBuilder(args);
var distributedCache = config.GetSection("DistributedCache");
if (distributedCache.Exists())
{
builder.Services.AddCoreDistributedCache(options =>
{
distributedCache.Bind(options);
if (options.Redis.Enabled)
{
var redisSection =
config.GetSection("DistributedCache:Redis");
var host =
redisSection["Host"] ?? "localhost:6379";
var password =
redisSection["Password"];
options.Redis.Configuration = redisConfig =>
{
redisConfig.EndPoints.Add(host);
if (!string.IsNullOrEmpty(password))
{
redisConfig.Password = password;
}
redisConfig.AbortOnConnectFail = false;
};
}
});
}
var app = builder.Build();
app.UseCoreDistributedCache();
app.Run();
π§βπ» Basic Usage
Inject ICoreCacheService into your services.
public class ProductService
{
private readonly ICoreCacheService _cache;
public ProductService(ICoreCacheService cache)
{
_cache = cache;
}
public async Task<Product> GetAsync(Guid id)
{
return await _cache.GetOrAddAsync(
$"product:{id}",
async () =>
{
return await LoadFromDatabase(id);
});
}
}
π― Advanced Usage: Provider Selection
public class MyBusinessService(ICacheServiceFactory cacheFactory)
{
public async Task SaveAsync(bool forceRedis)
{
var provider =
forceRedis
? CacheProviderType.Redis
: CacheProviderType.Memory;
var cache =
cacheFactory.GetCache(provider);
await cache.SetAsync(
"my_key",
myData,
TimeSpan.FromMinutes(5));
}
public async Task DefaultAsync()
{
var cache =
cacheFactory.GetDefaultCache();
await cache.GetOrAddAsync(
"default_key",
async () => GetData());
}
}
π·οΈ Declarative Caching
Caching logic can be applied declaratively using the [Cacheable] attribute.
This removes repetitive cache handling code from business services.
Example:
[HttpGet("data/{id}")]
[Cacheable(
tag: "Order",
expirationSeconds: 300)]
public async Task<IActionResult> GetData(string id)
{
var result =
await myService.GetDataAsync(id);
return Ok(result);
}
π Observability
The library integrates with OpenTelemetry Metrics.
| Metric | Description |
|---|---|
cache.distributed.hits |
Successful cache retrievals |
cache.distributed.misses |
Cache lookup misses |
cache.distributed.errors |
Provider errors |
cache.distributed.fallbacks |
Resilience fallback executions |
Compatible with:
- Grafana
- Prometheus
- Jaeger
- Azure Monitor
- Elastic Observability
- Any OTLP-compatible backend
π©Ί Health Checks
The package integrates with:
builder.Services.AddHealthChecks();
Provides monitoring for:
- Redis availability
- Memory cache status
- Provider connectivity
π οΈ Requirements
- .NET 8 SDK
- Microsoft.Extensions.Caching.Memory
- StackExchange.Redis
- OpenTelemetry
- Microsoft.Extensions.Diagnostics.HealthChecks
ποΈ Design Principles
FGutierrez.Core.DistributedCache follows:
- Clean Architecture principles
- Provider-based extensibility
- High cohesion / low coupling
- Cloud-native patterns
- Resilient infrastructure design
- Observability-first development
πΊοΈ Roadmap
Completed
- Memory Cache provider
- Redis provider
- Cache Aside pattern
- Resilience fallback
- OpenTelemetry metrics
- Health checks
- Declarative caching
Future
- SQL Server cache provider
- PostgreSQL cache provider
- Multi-level distributed cache
- Cache invalidation events
- Cache warming strategies
π€ Contributing
Contributions are welcome.
Steps:
- Fork the repository
- Create a feature branch
- Commit your changes
- Open a Pull Request
π License
MIT License
Β© Federin Pastor Gutierrez Ortiz
See the LICENSE file for details.
β Support
If this ecosystem helps you build modern .NET distributed systems, consider giving the repository a star on GitHub.
Building reusable cloud-native components, one package at a time.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- AspNetCore.HealthChecks.Redis (>= 8.0.1)
- FGutierrez.Core.Observability.Abstractions (>= 1.0.0)
- Microsoft.Extensions.Caching.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Caching.Memory (>= 8.0.1)
- OpenTelemetry (>= 1.15.3)
- OpenTelemetry.Extensions.Hosting (>= 1.15.3)
- StackExchange.Redis (>= 2.13.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.