-
Notifications
You must be signed in to change notification settings - Fork 156
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
AddOrUpdate and AddOrUpdateAsync methods [2] #150
Comments
This would be very helpful. Sometimes you need to update part of a cache. I don't think it is possible to do this in a thread safe way without implementing your own locking/synchronisation. In which case you would not use LazyCache. For example if I had a cache of "orders" which stores a list of orders ordered today. If I receive a new order, I want to add it to the list:
This not safe. What if another thread calls cache.Get() before this thread calls cache.Add() It would be a great addition if the cache could handle the necessary locking and the developer could do something like: Even if the developer was responsible for cloning or providing the new cache, it would still be a huge help:
I would be interested to hear what people have done to work around the problem so far... |
I think there is a few scenarios to unpack here, and how to handle them below, which might help explain why there is no AddOrUpdate. Say for some reasons I have a cached order record V1 and I know I want to update the cached instance of it and replace with V2. Say it is cached with key "order-123": A - I already have the new version V2 of the cached order in memory and all threads should start using it now B - I want to discard the current order and the next request should use the latest version of the order C - I want to generate the new version of the order, and any requests for the cached order that come in while I am generating must wait while generating v2 and must use the new version D - I want to generate the new version of the order in the background, and any requests for the cached order that come in while I am generating must use the existing V1. Once V2 is finished generated then use it So depending on the use case different behaviours can be achieved without the need for AddOrUpdate, and while being atomic, and Lazy (for A-C at least). There is one variant, in example D where the cached item expires during generation, and so you might then generate orderV2 more than once. Usually the best way to solve this is to be sure to refresh before cache expiry, such as on a timer. If you really wanted to handle D in a guaranteed atomic way then yes you would need a number of enhancements to LazyCache but in my experience the methods listed here have been sufficient for me. |
Thanks @alastairtree for this information. I think in cases C and D it would be useful to update. Imagine if you only want to increment a value in the cache without calling the expensive full load factory method. To update, you would need to call cache.Get() before calling cache.Add() or cache.Remove() which introduces the race condition. Do you agree? |
@jackfox10 That's exactly the scenario we got. We want to update the value in cache based on the previous value or add the new value if there's no previous value. |
Hello.
To continue closed #95 issue.
Your point that one can manually call Remove/Add is wrong. The whole point of this library is to provide thread-safe and atomic way to cache something evaluating a callback only once.
AddOrUpdate cannot be emulated with custom Remove/Add because it requires additional synchronization.
It can be useful when one know that element must be updated and such a request must be processed atomically.
Update callback must be provided with previous value and evaluated once.
The text was updated successfully, but these errors were encountered: