Invalidating Cache On Azure (or any distributed environment)

Topics: Core
Dec 19, 2011 at 7:42 PM

I like how caching is implemented in Orchard. there is no need to set an expiration time and it is all done using signals. and it relies on triggering tokens to invalidate the cache. however it is not Azure friendly because there is no way to trigger a Token across all role instances (setting IsCurrent to false on all instances).

Am I correct? is there is a simple workaround for this?

Dec 20, 2011 at 1:24 AM

That is correct, and caching for that reason should be applied carefully. The only way out of this is memcache-like solutions from what I understand. Sébastien could tell you more about this, if he sees this.

Dec 20, 2011 at 5:13 PM

We would need an AppFabric cache provider. I would beg you to do it if you can find an hour or two for that.

Dec 20, 2011 at 8:35 PM

I would love to make an AppFabric provider. I actually really need it :)

However I seriously doubt this is an hour or two kind of hack. here is why (I am not an expert btw):

  • First of all I strongly recommend making the provider based on Caching and then use the App Fabric cache provider for this will make our work reusable with other cache providers like memcache. either way I assume that AppFabric caching will only allow me to add objects by key and setting an expiration date on them
  • If I want to invalidate an item on AppFabric cache using any mean other than time based, I would have to call "Remove" on that object's key. Orchard on the other hand invalidates cache items when IsCurrent of a cache token returns false this is done even for time based expiration (see IClock). this leaves me with two problems:
    • How to evict items using Signals? (the current implementation maintains a dictionary of signal keys and tokens and sets IsCurrent to false when a signal is triggered. to replicate this on a distributed environment there needs to be an association with signal keys and cache keys so that we can call "Remove" on a cache key when a signal is triggered that should evict it. the solution that we come up with should take into consideration that an azure instance can create a signal (calling ISignals.When) and another completely different instance could invalidate it (calling ISignals.Trigger)
    • How to evict items using Time? the current implementation of IClock will have to be swapped into something that would pass the expiration time somehow to AppFabric caching.


I have also found some usage of caching that primarily assumes that Orchard is running on one Machine like in MonitorExtensions in DefaultOrchardHost the ShellContext is disposed when a cache item by the key "OrchardHost_Extensions" is invalidated. this means that only one instance of Azure will feel this change and dispose its shell while other instances would simply find the item in cache and not call DisposeShellContext.


I have also found (though not sure I understand it correctly please correct me if I am wrong) that orchard scopes cache by Type. Meaning that items stored in cache by class A will not be found in cache by class B. I came into this conclusion by looking at DefaultCacheManager.GetCache which sends the type of the class using the current instance of DefaultCacheManager (class A or B passed to it by CacheModule.AttachToComponentRegistration) to the ICacheHolder which uses it to construct a key to get the ICache which is used to get cached items. Is this correct?

Oct 16, 2012 at 3:10 PM

Wow, this discussion is kinda old... but I'll ask anyway: did anyone integrate AppFabric with Orchard? I'd be interested in how to do it. Similar to shadysayed I took a look at how caching works in Orchard and I'm still a bit confused. I'll try to look into it more and see if I can come up with something, but could use a few pointers.

Oct 17, 2012 at 12:02 PM

Oct 18, 2012 at 12:58 PM

@TheMonarch: that's quite interesting, but does it integrate with ICacheManager? I don't see any code that would make it possible for me to cache objects using ICacheManager and ISignals and have them go into the AppFabric cache. Or am I missing something? Other than that, I'll also take a look at the contrib caching module, I didn't see that until now and only now noticed the suppressions in your code. Thanks!

Oct 18, 2012 at 3:25 PM

AppFabric module is created by Nicholas, not me. I hadn't ever looked at the AppFabric module in detail, apparently it works on top of Contrib.Cache (output caching), not generic object caching. There are a ton of different interfaces in the Orchard Caching framework. What are they all for?