extensions
extensions copied to clipboard
[API Proposal]: HybridCache - should a HC-backed IDistributedCache be offered?
Background and motivation
Currently, HybridCache optionally consumes IDistributedCache (and IBufferDistributedCache via type-testing) as the L2 backend, typically for out-of-process/off-box storage (Redis etc).
A lot of existing code consumes IDistributedCache, and while in a perfect world they would migrate to HybridCache, we do not live in a perfect world, so there is a question as to whether it may be useful to optionally offer an IDistributedCache that is, effectively, a L1+L2 wrapper.
Considerations
- this option is only relevant when using L1+L2 (i.e. a non-trivial
IDistributedCachebackend); if you only want L1, there is alreadyAddDistributedMemoryCachewhich does exactly that - this would require careful configuration, to disambiguate the optional out-of-proc
IDistributedCachebackend from the exposed backend - this could be either via keyed-DI, or via explicit configuration against theHybridCacheOptions- further: many existing backends do not currently readily offer either a keyed-DI config, or a direct factory method; for example,
AddStackExchangeRedisCacheonly works on the default DI; maybe one option there is for the new exposed DI to be keyed? - see also keyed service topic here: https://github.com/dotnet/runtime/issues/109017
- further: many existing backends do not currently readily offer either a keyed-DI config, or a direct factory method; for example,
- the API would be different and would not have full feature parity, since
IDistributedCachehas separate get/put APIs - this is manageable, however - for correctness guarantees, we would need to perform defensive
byte[]copies when usingIDistributedCache, but that doesn't present a significant change - that is already expected - if done, it is easy to also support
IBufferDistributedCache(and we should do so), although should not expect massive usage; the entire point of things likeHybridCacheis to make that a non-concern for application code
Usage example
(entirely speculative and open to discussion)
// existing L2 registraction
services.AddStackExchangeRedisCache(...); // some L2
// existing service usage
public SomeService(IDistributedCache cache)
{
public async Task SomeMethodAsync()
{
// blah, cache.GetAsync etc
}
}
// new registration
services.AddHybridCache(...).WithKeyedDistributedCache("some key");
with the change to existing usage consisting of:
- public SomeService(IDistributedCache cache)
+ public SomeService([FromKeyedServices("some key")] IDistributedCache cache)
The downside of this is that it still requires per-usage changes, but that may be desirable anyway, to ensure the usage is fully considered.
Questions
- is this whole thing needed?
- is there a better way of handling the two separate
IDistributedCacheuses, that works better? - should the key be defaulted to something like
typeof(HybridCache)if not specified, or is that silly?