RepletoryLib.Caching.Abstractions
1.0.0
dotnet add package RepletoryLib.Caching.Abstractions --version 1.0.0
NuGet\Install-Package RepletoryLib.Caching.Abstractions -Version 1.0.0
<PackageReference Include="RepletoryLib.Caching.Abstractions" Version="1.0.0" />
<PackageVersion Include="RepletoryLib.Caching.Abstractions" Version="1.0.0" />
<PackageReference Include="RepletoryLib.Caching.Abstractions" />
paket add RepletoryLib.Caching.Abstractions --version 1.0.0
#r "nuget: RepletoryLib.Caching.Abstractions, 1.0.0"
#:package RepletoryLib.Caching.Abstractions@1.0.0
#addin nuget:?package=RepletoryLib.Caching.Abstractions&version=1.0.0
#tool nuget:?package=RepletoryLib.Caching.Abstractions&version=1.0.0
RepletoryLib.Caching.Abstractions
Caching abstractions and interfaces for the RepletoryLib ecosystem.
Part of the RepletoryLib ecosystem -- standalone, reusable .NET 10 libraries with zero business logic.
Overview
RepletoryLib.Caching.Abstractions defines the contracts for caching and distributed locking in the RepletoryLib ecosystem. By programming against these interfaces, your application code remains decoupled from any specific caching technology -- you can swap between in-memory, Redis, or hybrid caching without changing a single line of business logic.
This package contains interfaces only -- no implementations. Choose one of the implementation packages below based on your needs.
Choosing an Implementation
| Package | Technology | Best For |
|---|---|---|
RepletoryLib.Caching.InMemory |
IMemoryCache |
Single-instance apps, development, unit testing |
RepletoryLib.Caching.Redis |
StackExchange.Redis + RedLock.net | Distributed apps, production, persistent cache |
RepletoryLib.Caching.Hybrid |
InMemory (L1) + Redis (L2) | Best performance -- local speed with distributed consistency |
Key Features
ICacheService-- Get, set, remove, exists, prefix-based eviction, and cache-aside patternIDistributedLockService-- Acquire and release distributed locks for concurrency controlCacheOptions-- Shared configuration for default expiry, key prefix, and compression
Installation
dotnet add package RepletoryLib.Caching.Abstractions
Or add to your .csproj:
<PackageReference Include="RepletoryLib.Caching.Abstractions" Version="1.0.0" />
Note: RepletoryLib packages are published to a local BaGet feed. See the main repository README for feed configuration.
Dependencies
| Package | Type |
|---|---|
RepletoryLib.Common |
RepletoryLib |
Usage Examples
Cache-Aside Pattern
The most common caching pattern -- check the cache first, fall back to the data source, and populate the cache for next time:
using RepletoryLib.Caching.Abstractions.Interfaces;
public class ProductService
{
private readonly ICacheService _cache;
private readonly IProductRepository _repository;
public ProductService(ICacheService cache, IProductRepository repository)
{
_cache = cache;
_repository = repository;
}
public async Task<Product?> GetProductAsync(Guid id)
{
var cacheKey = $"product:{id}";
return await _cache.GetOrSetAsync(cacheKey, async () =>
{
return await _repository.GetByIdAsync(id);
}, TimeSpan.FromMinutes(30));
}
}
Basic Get / Set / Remove
using RepletoryLib.Caching.Abstractions.Interfaces;
public class SessionService
{
private readonly ICacheService _cache;
public SessionService(ICacheService cache) => _cache = cache;
public async Task CreateSessionAsync(string sessionId, UserSession session)
{
await _cache.SetAsync($"session:{sessionId}", session, TimeSpan.FromHours(1));
}
public async Task<UserSession?> GetSessionAsync(string sessionId)
{
return await _cache.GetAsync<UserSession>($"session:{sessionId}");
}
public async Task EndSessionAsync(string sessionId)
{
await _cache.RemoveAsync($"session:{sessionId}");
}
public async Task<bool> IsActiveAsync(string sessionId)
{
return await _cache.ExistsAsync($"session:{sessionId}");
}
}
Prefix-Based Cache Invalidation
Invalidate all cache entries that share a prefix:
// Cache product data with a shared prefix
await _cache.SetAsync("product:123:details", product);
await _cache.SetAsync("product:123:reviews", reviews);
await _cache.SetAsync("product:123:pricing", pricing);
// When the product is updated, evict everything related to it
await _cache.RemoveByPrefixAsync("product:123:");
Distributed Locking
Use IDistributedLockService to prevent concurrent access to shared resources:
using RepletoryLib.Caching.Abstractions.Interfaces;
public class PaymentProcessor
{
private readonly IDistributedLockService _locks;
public PaymentProcessor(IDistributedLockService locks) => _locks = locks;
public async Task ProcessPaymentAsync(Guid orderId, decimal amount)
{
var lockId = await _locks.AcquireAsync(
resource: $"payment:{orderId}",
expiry: TimeSpan.FromSeconds(30));
if (lockId is null)
throw new InvalidOperationException("Payment already being processed");
try
{
// Only one instance can process this payment at a time
await ChargeCustomerAsync(orderId, amount);
}
finally
{
await _locks.ReleaseAsync(lockId);
}
}
}
API Reference
ICacheService
public interface ICacheService
{
Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default);
Task SetAsync<T>(string key, T value, TimeSpan? expiry = null,
CancellationToken cancellationToken = default);
Task RemoveAsync(string key, CancellationToken cancellationToken = default);
Task RemoveByPrefixAsync(string prefix, CancellationToken cancellationToken = default);
Task<bool> ExistsAsync(string key, CancellationToken cancellationToken = default);
Task<T?> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null,
CancellationToken cancellationToken = default);
}
| Method | Description |
|---|---|
GetAsync<T> |
Retrieves a cached value by key. Returns null if not found. |
SetAsync<T> |
Stores a value with an optional expiry. Uses default expiry if not specified. |
RemoveAsync |
Removes a single cached entry. |
RemoveByPrefixAsync |
Removes all entries whose keys start with the given prefix. |
ExistsAsync |
Checks if a key exists in the cache. |
GetOrSetAsync<T> |
Cache-aside pattern -- returns cached value or invokes factory, caches the result, and returns it. |
IDistributedLockService
public interface IDistributedLockService
{
Task<string?> AcquireAsync(string resource, TimeSpan expiry,
CancellationToken cancellationToken = default);
Task ReleaseAsync(string lockId, CancellationToken cancellationToken = default);
}
| Method | Description |
|---|---|
AcquireAsync |
Attempts to acquire a lock on a resource. Returns a lock ID on success, null if the resource is already locked. The lock expires automatically after the specified duration. |
ReleaseAsync |
Releases a previously acquired lock by its lock ID. |
CacheOptions
public class CacheOptions
{
public int DefaultExpiryMinutes { get; set; } = 60;
public string KeyPrefix { get; set; } = "";
public bool EnableCompression { get; set; }
}
| Property | Type | Default | Description |
|---|---|---|---|
DefaultExpiryMinutes |
int |
60 |
Default cache entry lifetime when no expiry is specified |
KeyPrefix |
string |
"" |
Prefix prepended to all cache keys (useful for namespace isolation) |
EnableCompression |
bool |
false |
Enable compression for serialized cache values |
Integration with Other RepletoryLib Packages
| Package | Relationship |
|---|---|
RepletoryLib.Common |
Direct dependency -- provides base types |
RepletoryLib.Caching.InMemory |
In-memory implementation of ICacheService |
RepletoryLib.Caching.Redis |
Redis implementation of ICacheService and IDistributedLockService |
RepletoryLib.Caching.Hybrid |
L1/L2 implementation combining InMemory + Redis |
RepletoryLib.Auth.Jwt |
Uses ICacheService for token blacklist caching |
RepletoryLib.Testing |
Provides MockCacheService for unit testing |
Testing
Use MockCacheService from RepletoryLib.Testing to test code that depends on ICacheService:
using RepletoryLib.Testing;
public class ProductServiceTests : TestBase
{
[Fact]
public async Task GetProduct_caches_result()
{
Setup();
Services.AddTransient<ProductService>();
var provider = BuildServiceProvider();
var service = provider.GetRequiredService<ProductService>();
var product = await service.GetProductAsync(Guid.NewGuid());
MockCache.SetCalls.Should().HaveCount(1);
}
[Fact]
public async Task GetProduct_returns_cached_value()
{
Setup();
var productId = Guid.NewGuid();
var expected = new Product { Id = productId, Name = "Widget" };
await MockCache.SetAsync($"product:{productId}", expected);
Services.AddTransient<ProductService>();
var provider = BuildServiceProvider();
var service = provider.GetRequiredService<ProductService>();
var result = await service.GetProductAsync(productId);
result.Should().BeEquivalentTo(expected);
}
}
Troubleshooting
| Issue | Solution |
|---|---|
ICacheService not registered in DI |
You need to install and register an implementation package (InMemory, Redis, or Hybrid) |
IDistributedLockService returns null |
Only the Redis implementation supports distributed locks. InMemory has no lock support. |
| Cache keys colliding across services | Use CacheOptions.KeyPrefix to namespace keys per service or per tenant |
License
This project is licensed under the MIT License.
Copyright (c) 2024-2026 Repletory.
For complete documentation, infrastructure setup, and configuration reference, see the RepletoryLib main repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- RepletoryLib.Common (>= 1.0.0)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on RepletoryLib.Caching.Abstractions:
| Package | Downloads |
|---|---|
|
RepletoryLib.Caching.InMemory
In-memory caching implementation for RepletoryLib |
|
|
RepletoryLib.Caching.Redis
Redis caching implementation for RepletoryLib |
|
|
RepletoryLib.Testing
Test helpers, mocks, and base classes for RepletoryLib |
|
|
RepletoryLib.Auth.Jwt
JWT authentication and token management for RepletoryLib |
|
|
RepletoryLib.Ai.ContentGeneration
Template-based AI content generation with variable substitution, streaming, and optional caching for RepletoryLib |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 112 | 3/2/2026 |