A simple wrapper on StackExchange.Redis for connecting and interacting with a redis cache instance offering APIs for fetching, setting and invalidating cache items.
To register the required services simply call AddCacheManager
on the service collection i.e:
- Using hard coded values:
services.AddCacheManager(config => { config.ConnectionString = "localhost:6379"; });
- Binding with CacheManagerSettings from Configuration
services.AddCacheManager(config => Configuration.GetSection("CacheManager").bind(config));
The CacheKey
class creates a unique key by suffixing the provide key
with a named structure of the class in which is based off i.e:
var simpleCacheKey = new CacheKey<MyClass>("123"); // Produces: MyClass-123
var genericCacheKey = new CacheKey<IEnumerable<MyClass>>("123"); // Produces: IEnumerable`1<MyClass>-123
var nestedGenericCacheKey = new CacheKey<IDictionary<string, IEnumerable<MyClass>>>("123"); // Produces: IDictionary`2<String|IEnumerable`1<MyClass>>-123
This API has two overloads:
-
The first accepts a cacheKey and attempts to retrieve and deserialize the item from the cache.
public Task<MyClass?> GetCachedByIdAsync(string id) => _cacheManager.GetCacheItemAsync(new CacheKey<MyClass>(id));
-
The second overload provide additional parameters for retrieving and caching an item if not already in the cache.
public Task<MyClass> GetCachedByIdAsync(string id) => _cacheManager.GetCacheItemAsync( new CacheKey<MyClass>(id), async () => await _repository.GetByIdAsync(id), TimeSpan.FromMinutes(10));
API for adding an item to the cache:
public async Task PreloadIntegrationData()
{
var enumerator = _integration.GetAllResults().GetAsyncEnumerator();
var tasks = new List<Task>();
try
{
while (await enumerator.MoveNextAsync())
{
var currentResult = enumerator.Current;
var item = _mapper.Map<ApiResponse, MyClass>(currentResult);
tasks.Add(Task.Run(() => _cacheManager.CacheItemAsync(
new CacheKey<MyClass>($"integration-{item.Id}"),
item,
TimeSpan.FromMinutes(30))));
}
}
finally
{
await enumerator.DisposeAsync();
}
await Task.WhenAll(tasks);
}
API for invalidating an item in the cache which matches exactly the derived key:
public async Task<MyClass> UpdateByIdAsync(string id, string property)
{
var item = await _repository.SaveAsync((await _repository.GetByIdAsync(id)).Update(property));
await _cacheManager.InvalidateCacheItemAsync(new CacheKey<MyClass>(item.Id));
return item;
}
API for invalidating items with a key that contains the provided key:
public Task InvalidateIntegrationData()
=>_cacheManager.InvalidateCacheItemsByKeyPatternAsync("integration");