Caching Dynamically Modified Objects and the Trouble it Causes

03 Jul 2007

So I told you, in a previous post, about how our application has two parts: the live site and the cms. And that we want objects of the same class to behave differently in the two applications (only ‘live’ status objects should show up on the live site), which is not so hard in Ruby. But a few days later and after some conversations with our architect about how our caching works we realized that we had a huge bug.

We use memcached and cache-fu to cache our objects and we share that cache between the cms and the live site for the simple reason that we want an update to the object in cms to blow away the cache for the live site (otherwise the live site would never see the change as it would constantly be referencing the old cached version). But, as you may have already guessed, if the live site gets an object cached from the cms then all sorts of ‘draft’ stuff will show up on the public site because an object built in the cms will not have the extra special dynamically added add ons. Which is no good in a very serious way.

So after a long bit of trying to dynamically tap dance our way out of this mess, we realized (and by ‘we’ I mean Mike Ward) that the solution was to separate the caches with different namespaces and make sure the save callback blows away both. So all the objects cached by the cms have a prefix of ‘cms’ and all the live site objects have a prefix of ‘live’ and they never touch each other’s objects. Good. Then we added in an after_save hook that destroys both ‘cms-1234’ and ‘live-1234’ making sure that updated items will be seen as updated in both sites.

Yep, its a slight (probably very slight) performance hit now that the cms and the live site don’t share the same cache, but now we’re free to make the two rails instances behave the way they should without fear that they will get all messed up with each other. Nobody likes objects that sleep around.