Kanject.Core.CacheDb
A cache abstraction — ICacheDb — with three interchangeable providers: DynamoDB, S3 Express One Zone, and in-memory. Store strings or typed objects with an absolute expiry, read them back with a single TryGet, and namespace every key for per-stage isolation. Swap providers by swapping the registration call.
Providers
Install
dotnet add package Kanject.Core.CacheDb.Provider.DynamoDb# or .Provider.InMemory (tests / single process)# or .Provider.S3Express (S3 Express One Zone, ultra-low latency) Each provider is its own package; they all implement ICacheDb from Kanject.Core.CacheDb.Abstractions (pulled in transitively).
Register
using Kanject.Core.CacheDb.Provider.DynamoDb.Extensions;builder.Services.AddDynamoCacheDb(options =>{ options.CacheName = "orders-cache"; options.Namespace = appSettings.Stage; // per-stage key isolation options.AwsRegion = appSettings.AwsRegion; options.TTL = 15; // default item lifetime, in minutes}); The S3 Express provider takes the same shape plus AvailabilityZoneId; the in-memory provider takes just a namespace string. Namespace prefixes every key, so dev and prod can share an account without colliding.
Use it
Inject ICacheDb. Build a namespaced key with FormatCacheKey, try-get, and on a miss compute and store with an absolute expiry (a DateTime, not a relative TTL):
public class QuoteService(ICacheDb cache, IPricingApi pricing){ public async Task<string> GetQuoteAsync(string sku) { var key = cache.FormatCacheKey("quote", sku); var (hit, cached) = await cache.TryGetCacheDataAsync(key); if (hit) return cached!; var quote = await pricing.QuoteAsync(sku); // Absolute expiry — pass the DateTime the entry should die at. await cache.CacheDataAsync(key, quote, DateTime.UtcNow.AddMinutes(5)); return quote; }} Typed overloads serialize and deserialize any object; removal takes one or many keys:
// Typed overloads serialize/deserialize with System.Text.Json.await cache.CacheDataAsync("basket:" + userId, basket, DateTime.UtcNow.AddHours(1));var (found, basket) = await cache.TryGetCacheDataAsync<Basket>("basket:" + userId);// Invalidate one or many keys.await cache.RemoveCachedDataAsync("basket:" + userId); What ships with it
- One
ICacheDbinterface, three providers — DynamoDB, S3 Express One Zone, in-memory CacheDataAsync(key, value, DateTime? expiry)— string and typed (<T>) overloads, System.Text.Json serializationTryGetCacheDataAsync(key)→(bool exists, value)— string and typed overloadsRemoveCachedDataAsync(params string[] keys)— invalidate one or many keysFormatCacheKey(params string[] keys)+ aNamespaceprefix for per-stage / per-tenant isolation- Lock, counter-lock, and seat-lock helpers with the same surface across providers