-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Background and motivation
Microsoft.Extensions.Caching.Hybrid
an API for adding a HybridCache
to the application's service collection, and the AddHybridCache()
method results in constructing a DefaultHybridCache
singleton. DefaultHybridCache
respects that an IDistributedCache
service might be registered, and that cache will be used for an L2 cache provider.
Applications can use keyed services to register multiple IDistributedCache
services for use throughout the application, but the DefaultHybridCache
cannot consume these keyed services. Moreover, if DefaultHybridCache
could respect a distributed cache service key, that would lead to the need for registering multiple HybridCache
services into the collection using keyed services.
Because DefaultHybridCache
is internal and can only be registered into the service collection via AddHybridCache()
, there are no clear paths toward registering multiple instances that consume different keyed services for the distributed caches.
API Proposal
namespace Microsoft.Extensions.Caching.Hybrid;
public class HybridCacheOptions
{
public HybridCacheEntryOptions? DefaultEntryOptions { get; set; }
public bool DisableCompression { get; set; }
public long MaximumPayloadBytes { get; set; }
public int MaximumKeyLength { get; set; }
public bool ReportTagMetrics { get; set; }
+ public object? DistributedCacheServiceKey { get; set; }
}
namespace Microsoft.Extensions.DependencyInjection;
public static class HybridCacheServiceExtensions
{
public static IHybridCacheBuilder AddHybridCache(this IServiceCollection services, Action<HybridCacheOptions> setupAction);
public static IHybridCacheBuilder AddHybridCache(this IServiceCollection services);
+ public static IHybridCacheBuilder AddKeyedHybridCache(this IServiceCollection services, object? serviceKey, Action<HybridCacheOptions> setupAction);
+ public static IHybridCacheBuilder AddKeyedHybridCache(this IServiceCollection services, string serviceKey);
}
API Usage
var services = new ServiceCollection();
services.AddKeyedSingleton<IDistributedCache, RedisCache>(typeof(RedisCache));
services.AddKeyedSingleton<IDistributedCache, SqlServerCache>(typeof(SqlServerCache));
services.AddKeyedHybridCache("HybridRedis", options => options.DistributedCacheServiceKey = typeof(RedisCache));
services.AddKeyedHybridCache("HybridSqlServer", options => options.DistributedCacheServiceKey = typeof(SqlServerCache));
using ServiceProvider provider = services.BuildServiceProvider();
var redisHybrid = Assert.IsType<DefaultHybridCache>(provider.GetRequiredKeyedService<HybridCache>("HybridRedis"));
var sqlHybrid = Assert.IsType<DefaultHybridCache>(provider.GetRequiredKeyedService<HybridCache>("HybridSqlServer"));
Alternative Designs
- Make DefaultHybridCache public and expand its API surface area to allow specification of the distributed cache service key
- Refactor reusable logic out of DefaultHybridCache so that other cache implementations can compose that logic differently, such as using keyed services
- Pass the distributed cache service key into
AddKeyedHybridCache
as another argument instead of adding it as a property toHybridCacheOptions
. Adding to the options is preferred as this allows the cache key to be included in the application configuration without code to wire the two together.
Risks
- The implementation with this design is not yet complete; wiring up the keyed options still needs to be finished. It's possible the type(s) of the service key values might need to be changed.
- If the options are not wired up correctly into the keyed singletons, the wrong backend cache could be used.