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

MemoryCache: "Cannot update the item that is not yet expired." #1017

Closed
mholzmann-medi opened this issue Dec 20, 2021 · 11 comments
Closed

MemoryCache: "Cannot update the item that is not yet expired." #1017

mholzmann-medi opened this issue Dec 20, 2021 · 11 comments
Assignees
Labels
question Further information is requested todo Things to be done in the future

Comments

@mholzmann-medi
Copy link

I use the MemoryCache implementation and have problems in a multi-threaded environment.

When I call a Query() method with the same cacheKey from different threads, I get a "Cannot update the item that is not yet expired." exception. Why can't I update a cached item when it is not expired yet?

Does this mean that I can't use the caching within a multi-threaded environment?

Thanks.

@mholzmann-medi mholzmann-medi added the question Further information is requested label Dec 20, 2021
@mikependon
Copy link
Owner

To ensure that caching mechanism is intact and will not be polluted, we did restrict adding an item to the MemoryCache object with the same key (that has not yet expired), unless of course you explicitly expire the existing cache item and add a new one manually.

But, your problem is not related to the persistency of the cache item. Upon the initial investigation, it sounds to us that the Add method has been invoked twice at the same time and that hits the validation code during caching, in which technically should not happen.

ConcurrentDictionary worked as expected (thread-safe) in your scenario, but our validation has not.

We will look into this and revert back you ASAP. We will also include the fix to this (if there is) on the next major release.

@mikependon
Copy link
Owner

Temporary solution, can you identify the 2nd thread and delay it for just 1 sec?

@mholzmann-medi
Copy link
Author

Thanks for your quick reply.

I quickly implemented a MemoryCache class clone and modified the Add<T>(CacheItem<T> item, bool throwException = true) method to re-add new CacheItem:

if (!item.IsExpired() && throwException == true)
  throw new InvalidOperationException("Cannot update the item that is not yet expired.");

this.cache.AddOrUpdate(item.Key, key => new CacheItem<T>(item.Key, item.Value, item.CacheItemExpiration ?? Constant.DefaultCacheItemExpirationInMinutes), (key, val) => new CacheItem<T>(item.Key, item.Value, item.CacheItemExpiration ?? Constant.DefaultCacheItemExpirationInMinutes));

The disadvantage here is currently that I can't set the Value and CacheItemExpiration properties, so a new instance must be created. But now it works as expected.

@mikependon
Copy link
Owner

You should be able to set the expiration of the cache item by accessing actual CacheItem itself.

public DateTime Expiration { get; set; }

FYI, we do understand your scenario about multi-threaded calls on the same item from the database. This problem needs to be fixed fundamentally.

We will consider your fix on our fix to this issue.

@mikependon mikependon self-assigned this Dec 20, 2021
@mikependon mikependon added the todo Things to be done in the future label Dec 20, 2021
@mikependon mikependon pinned this issue Dec 20, 2021
@mikependon
Copy link
Owner

FYI: The issue can be replicated by this project solution (Issue1017.zip).

mikependon added a commit that referenced this issue Dec 20, 2021
…eaded environment.

Behavioral Change: When calling the MemoryCache.Add method, the existing cached item (if present) information will be updated by the latest and updated one.
mikependon added a commit that referenced this issue Dec 20, 2021
#1017 - Added a fix to the failing UpdateFrom method on the Multi-Thr…
@mikependon
Copy link
Owner

The fix has been added on the main branch. It will be a part of the next release (beta or actual).

Note: There is a behavioral change on this. When calling the MemoryCache.Add method, the existing cached item (if present) information will be updated by the latest and updated one.

@mikependon mikependon unpinned this issue Dec 20, 2021
@mholzmann-medi
Copy link
Author

@mikependon Can you tell me when the next release will be? Thanks a lot.

@mikependon
Copy link
Owner

February 2nd week is our plan. Do you need the beta release for this?

@mholzmann-medi
Copy link
Author

Thanks for your update. A beta release would be fine! Thanks.

@mholzmann-medi
Copy link
Author

@mikependon
Do you hava any release date? Thanks.

@mikependon
Copy link
Owner

We will soon use the timeline page for more visibility. This is plan before end of this week. FYI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested todo Things to be done in the future
Projects
None yet
Development

No branches or pull requests

2 participants