MichaCo / CacheManager

CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features.
http://cachemanager.michaco.net
Apache License 2.0
2.33k stars 458 forks source link

No Remove notification when using MemoryCacheHandle with RedisCacheBackplane but without RedisCacheHandle #311

Open erizzo opened 4 years ago

erizzo commented 4 years ago

When using a cache configuration as described here by Micha, it's possible that Remove notifications don't get sent via the backplane. If I have 2 processes configured in that way , it's possible that one of the process' (let's call it P1) in-memory cache handle will contain a particular value while the other (P2) does not. For example, a situation with 2 instances of an API, where one instance has served (and thus cached) the object, but the other instance has not (yet) served a request for that key. Now if something happens in P2 that would invalidate the cache for that key, a call to Remove() will not send the notification over the backplane. That's because of some code in BaseCacheManager.RemoveInteral(), here. Note that on lines 501 or 505, the bool result of handle.Remove() is used to set a variable called result. Only if result is true (line 524), will the backplane get notified of the removal. Which means, if none of the handles (in this configuration, there is only the in-memory handle), currently contains the value, its Remove() will return false and thus no backplane message, thus the other process is never told that the key was removed. It leads to stale data existing in the cache of P1.

We encountered this in a real application; the simplest workaround we found was to first Store() a dummy value under the key right before calling Remove(), which ensured that Remove() returned true and the backplane message got sent.

erizzo commented 4 years ago

As a potential solution, could you check during RemoveInternal() if there is no distributed handle, and if not go ahead with the notification even if handle.Remove() returns false?