Jake Scruggs

writes ruby/wears crazy shirts

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.

2 comments :

Chris said...

Do you really need to cache objects for the CMS? Why not just hit the database directly, assuming the load CMS users produce is significantly less than that of the public site's visitors.

Jake Scruggs said...

Originally, we cached the cms only to make sure that a cms save will propagate to the live site (saving blows away the (previously) shared cache). If we just had the cms go straight at the db, then how would the live site know to stop using it's cached object and go get an updated one? Now that the cache keeps the sites separate, we could stop caching the cms and just make sure a cms save clears the cache but this is a pretty well used cms (lots of markets and users) and the caching doesn't seem to be doing any harm.