[API Proposal]: HybridCache - should a HC-backed IDistributedCache be offered? #5539
Open
Description
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
IDistributedCache
backend); if you only want L1, there is alreadyAddDistributedMemoryCache
which does exactly that - this would require careful configuration, to disambiguate the optional out-of-proc
IDistributedCache
backend 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,
AddStackExchangeRedisCache
only works on the default DI; maybe one option there is for the new exposed DI to be keyed? - see also keyed service topic here: [API Proposal]: Keyed services; alternative registration API for existing non-keyed services runtime#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
IDistributedCache
has 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 likeHybridCache
is 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
IDistributedCache
uses, that works better? - should the key be defaulted to something like
typeof(HybridCache)
if not specified, or is that silly?