Open maryamariyan opened 3 years ago
Tagging subscribers to this area: @eerhardt, @maryamariyan
See info in area-owners.md if you want to be subscribed.
Issue meta data
Issue content: | As @eerhardt and I were triaging through caching extensions issues, we noticed a theme of requests being around request to allow for key enumeration and bulk removal of items in IDistributedCache: - [ ] #36547: How to flush all cache - [ ] #36568: Bulk remove on IDistributedCach - [ ] #36402: Enumerating keys using IDistributedCache We closed a number of items as dupes of the above issues as well. More information on the intricacies of this issue and ways to approach it: - When using caching in extensions, we don't want to allow enumerating on keys while elements may get removed within another thread, (keeping as atomic operation). In order to allow for (e.g. bulk remove) we can offer returning a snapshot (say array of elements. For example to allow for bulk remove of items with a certain prefix (e.g. "ZZZ"), given a snapshot, we may use TryGetValue and if already gone it would not throw. |
Issue author: | maryamariyan |
Assignees: | - |
Milestone: | - |
- ..... For example to allow for bulk remove of items with a certain prefix (e.g. "ZZZ"), given a snapshot, we may use TryGetValue and if already gone it would not throw.
@maryamariyan, StackExchange.Redis.IDatabase.KeyDeleteAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None)
does not throw an exception if a key is not found. See - https://github.com/StackExchange/StackExchange.Redis/blob/6409b9d1f2afd01a7eab9498a525360d1ca2b752/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs#L442
Is there a concern I'm missing?
I wonder if it is being worked on. I recently stumbled upon a case when I very much need to enumerate values (or keys at least) by pattern (prefix), otherwise I will have to use underlying caching solution directly, which breaks my abstractions.
It looks like this has been added to the .NET 6.0 milestone (tentatively sched to be released in November 2021 - https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-2/#:~:text=.NET%206%20will%20be%20released,Term%20Support%20(LTS)%20release.
We've reached feature complete for .NET 6. Moving to 7.
So this is being bumped again to .NET 8 now?
@avisra this is still being considered for 7.0 as a nice to have but not committed
@avisra I was looking to learn more about how IDistrbutedCache is being used? do you have sample code snippets to share to kick this off?
@maryamariyan I am currently using IDistributedCache for caching data in my application (and for caching things within my IdentityServer instance). On my deployed application, I am configuring my cache to use Redis. Locally, I am using in-memory. But regardless of the provider, it is going through IDistributedCache. My goal for this ticket is to be able to enumerate the cache without identifying the provider. I'd like to have a page in the administration of my application which displays a table with all of the objects in my cache (by key) and have a button for deleting/revalidating, etc. The only piece missing from this, which I'm hoping this ticket can provider, is the ability to enumerate the objects in the cache collection.
@avisra Here are a couple of potential interface additions for IDistributedCache
for getting and performing common tasks with keys.
// retrieve a list of keys list synchronously using a pattern (pattern will be third-party dependent)
IEnumerable<string> Keys(string pattern);
// retrieve a list of keys asynchronously using a pattern (pattern will be third-party dependent)
Task<IEnumerable<string>> KeysAsync(string pattern);
// retrieve a list of values synchronously based on a set of keys
IEnumerable<byte[]> Get(param string[] keys);
// retrieve a list of values asynchronously based on a set of keys
Task<IEnumerable<byte[]>> GetAsync(param string[] keys);
// remove a list of values synchronously based on a set of keys
void Remove(param string[] keys);
// remove a list of values asynchronously based on a set of keys
Task RemoveAsync(param string[] keys);
// refresh a list of values synchronously based on a set of keys
void Refresh(param string[] keys);
// refresh a list of values asynchronously based on a set of keys
Task RefreshAsync(param string[] keys);
usage:
// assume that the developer will have a wrapper that converts from bytes (used in `IDistrubutedCache` interface) to a .net value type or reference type.
// redis specific example. using star (*) as the wildcard
var allAccessTokenKeys = _redisCacheService.Keys("AccessTokens:*");
foreach(var key in allAccessTokenKeys)
{
Console.WriteLine(key);
}
// get all the values for all the keys we retrieved above
var allAccessTokens = _redisCacheService.Get(allAccessTokenKeys.ToArray());
foreach(var token in allAccessTokens)
{
Console.WriteLine(token);
}
// refresh all allAccessTokens in the cache, so they don't expire
_redisCacheService.Refresh(allAccessTokenKeys.ToArray());
// remove all allAccessTokens from the cache, except a special one
_redisCacheService.Remove(allAccessTokenKeys.Where(a => a.Equals("AccessTokens:MySpecialKey") == false).ToArray());
It seems that this is already possible with libraries such as EasyCaching.
As @eerhardt and I were triaging through caching extensions issues, we noticed a theme of requests being around allowing for key enumeration and bulk removal of items in IDistributedCache:
We closed a number of items as dupes of the above issues as well.
More information on the intricacies of this issue and ways to approach it: