Changing RedisCacheOptions after registering the StackExchangeRedisCache middleware

Viewed 319

I'm trying to use Redis in my Asp.Net Core project. I added the packages StackExchange.Redis and Microsoft.Extensions.Caching.StackExchange.Redis to my project and the following code to register the middleware:

services.AddStackExchangeRedisCache(options =>
{
  // do config
});

So far that works fine. But in this project Configuration settings are provided by a custom ConfigurationService which is pulling them from an external source. If changes in any of the configuration settings concerning Redis are detected I need to be able to reconfigure the StackExchangeRedisCache middleware.

How would I do that?

1 Answers

If I get the question right, does the case is... The project configuration setting was customize to fetch from another source by some interval ? Therefore, the setting on redis could change by time to time ?

If that's the case, I think we got to drop usage of AddStackExchangeRedisCache extensions. If you want to keep using this, here is some problem that got to solve:

  • Remove RedisCache singleton instance that previously register in ServiceCollection.
  • Remove config for RedisCacheOptions previously register in ServiceCollection
  • Register new RedisCacheOptions and RedisCache in ServiceCollection
  • Re-initialize ServiceProvider somehow
  • These step should be done atomicity, otherwise, exceptions likely to raise.

Quite cumbersome... does it ?

Another approach was to create a placeholder for IDistributedCache instance, register it as singleton and update the IDistributedCache instance if change was detected from the Configuration.

// Place holder, and register it as singleton
public class CacheAccessor : IDisposable
{
    private RedisCache RedisCache { get; set; }

    public void SetRedisCache(IOptions<RedisCacheOptions> options)
    {
        RedisCache?.Dispose();
        RedisCache = new RedisCache(options);
    }

    public IDistributedCache LatestRedisCache => RedisCache;

    public void Dispose()
    {
        RedisCache?.Dispose();
    }
}

// Register it
services.AddSingleton<CacheAccessor>();

// Initialize it for the first time (write some extension or put it somewhere in program.cs would be nice.
// Run after the webhost instance got built and before it run)
// host was an instance of IHost
using var scope = host.Services.CreateScope();
var serviceProvider = scope.ServiceProvider;
serviceProvider.GetRequiredService<CacheAccessor>().SetRedisCache(Pass the option here).

// By time to time, if the config changed, extract the option and SetRedisCache again.

// And of course, get access to the cache would be difference
public IActionResult TestMethod([FromServices] CacheAccessor accessor)
{
    var cache = accessor.LatestRedisCache;
}
Related