I need a way to run some code on all instances of a site. Specifically I want to clear objects with a certain key in the HttpRuntime Cache, and do this on all instances running the site. Clearing the cache on one instance is straightforward, but how do I make sure this affects all web instances?
This is not IContent-objects so as far as I can tell I can't use EPiServers distributed cache mechanisms. I also don't control the code adding objects to the cache.
We're running Episerver 11.2.1 in DXC cloud.
Yes, you can use ISynchronizedObjectInstance cache for your custom objects. When you call Remove() the remote event system will be used to remove the key from the cache on all connected instances. I suggest you also use ISynchronizedObjectInstanceCache for Insert() and Get() as well, rather than using e.g. HttpRuntime.Cache directly.
Unfortunately there is external code that is adding the objects to the cache so I can't make them use the ISynchronizedObjectInstance cache. However you pointed me to looking at the Event Api so I think I will try to use that to run the code on all instances. I will just have to find a way to test it.. :). I'll get back when I know if it works out or not.
If you are in control of the Remove() calls you can use ISynchronizedObjectInstanceCache only for that. Since the default ISynchronizedObjectInstanceCache implementation uses HttpRuntimeCache it should work anyway.
Hmm... That would require all Cache keys to be distributed by the ISynchronizedObjectInstanceCache, right? Otherwise you would still need to clear the cache individually on each instance, since each instance is likely to have different sets of cached objects.
Calling ISynchronizedObjectInstanceCache.Remove is (with the default implementation) equivalent to calling HttpRuntime.Cache.Remove on each of the instances. It does not matter if they all have the key in cache or not. Remove works as "Remove if exists".
What I'm hinting at is that to know which objects to remove I will have to iterate through the cache and find all objects with a cachekey starting with a certain prefix.
If I do this iteration on only one instance there will be 1) objects that are not in the cache on the other instances. This case is ok, as these only will be removed where they exist. But there will also be 2) some objects on the other instances that are not on the first instance, and these will be left in the cache since the instance executing the Remove()s are not aware of them.
Speaking from experience, I would say: Never iterate the cache. It could come at a horrible performance penalty.
It sounds like you would want to insert objects with dependencies to a master key (see the CacheEvictionPolicy class), so that you can remove the master key and have the dependent items evicted with it. But you were not in control of inserting the items? That doesn't sound like an ideal situation... Could you configure the lib or whatever you are using to not cache, or to cache with a minimum timeout? And add a cache layer yourself so you can work with dependencies.
We are using a third party solution to serve images. In order to reduce calls to their remote server we are about to activate the sdk client cache mechanism they provide. We pretty much trust this cache and we also initially aim to have a fairly long cache time. We trust that editing what image to serve will effectively invalidate the cache. There are however edge cases where it may fail. E.g. when an asset gets updated on the remote server (which however rarely/never) happens. So this cache invalidation mechanism I've implemented is just a safety vent meant for manual activation. Therefore I'll accept the performance aspect of iterating the cache :).