Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to flush all cache? #36547

Closed
PrimeObjects opened this issue Aug 19, 2015 · 16 comments
Closed

How to flush all cache? #36547

PrimeObjects opened this issue Aug 19, 2015 · 16 comments

Comments

@PrimeObjects
Copy link

No description provided.

@Tratcher
Copy link
Member

Related: aspnet/Caching#93

@basitanwer
Copy link

Responding to dotnet/extensions#93 being related

I think and support there should be a cache clear option. Reasons could be

  1. Development and testing is made easier.
  2. With multiple Clients connected, keeping a local map of keys won't do the trick.
  3. Scanning over all the items to do this isn't a great idea
  4. All existing Distributed Caches support clear operations.

@blakepell
Copy link

I was curious about the same thing. Further, from a diagnostics perspective I wanted to know everything that was in the cache (the argument of whether or I should or shouldn't iterate over cache keys aside). If I cast IMemoryCache that was injected as MemoryCache I was able to get the Count property but no keys exposed. Looking at the MemoryCache class there was just a Dictionary behind it like in past versions.

I forked the project at RC1, added a Keys property onto the MemoryCache class that returned the keys from the Dictionary. Built that, put the Nuget output into my custom Nuget feed and then updated my Nuget packages and let it do the rest.

@RehanSaeed
Copy link

+1 to adding a Clear() method to IMemoryCache and IDistributedCache.

I now expose a cache clearing method in my controllers as a matter of course. This stops you having to use the nuclear option of restarting the site to clear IMemoryCache or having to go off to Redis to clear IDistributedCache.

As it is, I will now have to keep a list of all my keys. Not a fun thing to do.

@RehanSaeed
Copy link

RehanSaeed commented Apr 12, 2016

For those looking for a workaround, I have written and tested the following helper class with a ClearAsync, GetKeysAsync and a bulk RemoveAsync method which lets you remove multiple keys. It just needs to be added to the IServiceCollection DI container for use. Am willing to create a PR with these methods added if required.

public class DistributedCacheExtended : IDistributedCacheExtended, IDisposable
{
    private const string ClearCacheLuaScript =
        "for _,k in ipairs(redis.call('KEYS', ARGV[1])) do\n" +
        "    redis.call('DEL', k)\n" +
        "end";
    private const string GetKeysLuaScript = "return redis.call('keys', ARGV[1])";
    private readonly RedisCacheOptions options;
    private ConnectionMultiplexer connection;
    private IDatabase cache;
    private bool isDisposed;

    public DistributedCacheExtended(IOptions<RedisCacheOptions> redisCacheOptions)
    {
        this.options = redisCacheOptions.Value;
    }

    ~DistributedCacheExtended()
    {
        this.Dispose(false);
    }

    public async Task ClearAsync()
    {
        this.ThrowIfDisposed();
        await this.EnsureInitialized();
        await this.cache.ScriptEvaluateAsync(
            ClearCacheLuaScript,
            values: new RedisValue[]
            {
                this.options.InstanceName + "*"
            });
    }

    public async Task<IEnumerable<string>> GetKeysAsync()
    {
        this.ThrowIfDisposed();
        await this.EnsureInitialized();
        var result = await this.cache.ScriptEvaluateAsync(
            GetKeysLuaScript,
            values: new RedisValue[]
            {
                this.options.InstanceName + "*"
            });
        return ((RedisResult[])result).Select(x => x.ToString().Substring(this.options.InstanceName.Length)).ToArray();
    }

    public async Task RemoveAsync(string[] keys)
    {
        this.ThrowIfDisposed();
        if (keys == null) { throw new ArgumentNullException(nameof(keys)); }
        await this.EnsureInitialized();
        var keysArray = keys.Select(x => (RedisKey)(this.options.InstanceName + x)).ToArray();
        await this.cache.KeyDeleteAsync(keysArray);
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected async Task EnsureInitialized()
    {
        if (connection == null)
        {
            this.connection = await ConnectionMultiplexer.ConnectAsync(this.options.Configuration);
            this.cache = this.connection.GetDatabase();
        }
    }

    private void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing && this.connection != null)
            {
                this.connection.Close();
            }

            this.isDisposed = true;
        }
    }

    private void ThrowIfDisposed()
    {
        if (this.isDisposed)
        {
            throw new ObjectDisposedException(nameof(DistributedCacheExtended));
        }
    }
}

@Grauenwolf
Copy link

This is what I currently have to do with System.Runtime.Caching:

public void CacheBuster()
    {
        //Unfortunately Cache doesn't have a Clear method, so we have to do this the hard way.

        var memoryCache = Cache as MemoryCache;
        if (memoryCache != null)
            memoryCache.Trim(100); //this will clear most, but not all, of the cache.

        //This accounts for all cache types, not just MemoryCache.
        foreach (var item in Cache)
            Cache.Remove(item.Key);
    }

I really, really want to stop doing this.

@aspnet-hello aspnet-hello transferred this issue from aspnet/Caching Dec 13, 2018
@NickeManarin
Copy link

So, @RehanSaeed what's the status on this matter? Do you have an example?

@RehanSaeed
Copy link

Sadly, nothings changed. Still waiting for this functionality.

@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label May 15, 2020
@analogrelay analogrelay transferred this issue from dotnet/extensions May 15, 2020
@analogrelay analogrelay added this to the Future milestone May 15, 2020
@maryamariyan maryamariyan removed the untriaged New issue has not been triaged by the area owner label Jul 1, 2020
@tonyqus
Copy link

tonyqus commented Jul 15, 2020

The issue has been open for 5 years. Nothing changed. It's a very common request to clear all cache items in the memory.

@mou7866
Copy link

mou7866 commented Jul 27, 2020

Please can this issue be added as I am having immense issues flushing keys manually. Thank you

@danmoseley
Copy link
Member

danmoseley commented Jul 27, 2020

What would this look like as an API? (general format shown in https://github.com/dotnet/runtime/issues/new?assignees=&labels=api-suggestion&template=02_api_proposal.md&title=)

@maryamariyan maryamariyan modified the milestones: Future, 6.0.0 Sep 30, 2020
@maryamariyan
Copy link
Member

Related to #36568

@adamsitnik
Copy link
Member

I've created a new issue with the proposal: #45593

@eerhardt
Copy link
Member

We've reached feature complete for .NET 6. Moving to 7.

@eerhardt eerhardt modified the milestones: 6.0.0, 7.0.0 Jul 19, 2021
@eerhardt
Copy link
Member

A Clear() method was added to MemoryCache in #45593. Closing as completed.

@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests