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

Enhancement to IDistributedCache - Allow for bulk remove and key enumeration #44512

Open
3 tasks
Tracked by #44314 ...
maryamariyan opened this issue Nov 11, 2020 · 11 comments
Open
3 tasks
Tracked by #44314 ...
Labels
area-Extensions-Caching Bottom Up Work Not part of a theme, epic, or user story Epic Groups multiple user stories. Can be grouped under a theme. Team:Libraries User Story A single user-facing feature. Can be grouped under an epic.
Milestone

Comments

@maryamariyan
Copy link
Member

maryamariyan commented Nov 11, 2020

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:

  • 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.
@maryamariyan maryamariyan added untriaged New issue has not been triaged by the area owner area-Extensions-Caching User Story A single user-facing feature. Can be grouped under an epic. labels Nov 11, 2020
@ghost
Copy link

ghost commented Nov 11, 2020

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:

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: -

@maryamariyan maryamariyan added this to the 6.0.0 milestone Nov 11, 2020
@maryamariyan maryamariyan removed the untriaged New issue has not been triaged by the area owner label Nov 11, 2020
ShreyasJejurkar added a commit to ShreyasJejurkar/runtime that referenced this issue Nov 11, 2020
Added corresponding tests scenarios as well.

As part of dotnet#44512
@danmoseley danmoseley added the Bottom Up Work Not part of a theme, epic, or user story label Dec 1, 2020
@udlose
Copy link

udlose commented Dec 31, 2020

  • ..... 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?

@kosmakoff
Copy link

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.

@udlose
Copy link

udlose commented Mar 17, 2021

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.

@eerhardt
Copy link
Member

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

@avisra
Copy link

avisra commented Jan 21, 2022

So this is being bumped again to .NET 8 now?

@maryamariyan
Copy link
Member Author

maryamariyan commented Feb 1, 2022

@avisra this is still being considered for 7.0 as a nice to have but not committed

@maryamariyan
Copy link
Member Author

@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?

@avisra
Copy link

avisra commented Feb 16, 2022

@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.

@Strandedpirate
Copy link

@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());

@maryamariyan maryamariyan modified the milestones: 7.0.0, 8.0.0 Jun 14, 2022
@maryamariyan maryamariyan added the Epic Groups multiple user stories. Can be grouped under a theme. label Oct 18, 2022
@wilkovanderveen
Copy link

It seems that this is already possible with libraries such as EasyCaching.

@adamsitnik adamsitnik modified the milestones: 8.0.0, 9.0.0 Jul 28, 2023
@adamsitnik adamsitnik modified the milestones: 9.0.0, Future Jul 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Extensions-Caching Bottom Up Work Not part of a theme, epic, or user story Epic Groups multiple user stories. Can be grouped under a theme. Team:Libraries User Story A single user-facing feature. Can be grouped under an epic.
Projects
None yet
Development

No branches or pull requests

9 participants