smartly_caches, smarter than ever
11
Please note that the problem introduced here and the technique proposed to
solve it can be applied for any RESTful web application. The post might be
using Rails terminologies/expressions/code only for demonstration.
Consider the following scenario: You access a resource namely "item" via a
simple restful get request (items/1). You want to cache the response of that
request, and expire that cache if any model (database) changes occurs to that
specific item (with id =1).
The straight forward (ugly) solution is to expire the cached response
explicitly in other actions of the controller (ie. Update and Destroy).
Rails sweepers aim to simplify some of the coupling between controller code and
cache expiry code and spare you from using the expire_xxx methods directly in
the actions of your controller. Typically you need one sweeper per controller.
However as your code grows, this becomes very tedious and hard to maintain as
well.
It would be great if we can no more worry about the expiry code at all, and let
a smart caching server (like memcached) do auto expiry using appropriate (LRU?)
techniques.
This leaves us with the problem of getting an old cached response if the
resource (db record) bound to that request has actually changed. The solution
is model versioning. We can version our (Item) model and update the version of
the corresponding record on each resource (db) update. One possible
implementation for this may be done by adding a "version" column to the "items"
table and update it as appropriate. A smarter way is to keep the db untouched
and save the version in your cache store with the pair (model name, id) as the
key (for example Item_1) and the version is the value. Enough talk, here’s a
piece of code that illustrates this…
And then of course we must have an observer for the Item model that updates
the version of each item on various updates; so that when a specific item gets
updated (in our example item 1) the value of the key "Item_1" is updated in the
cache store allowing cache_response to behave correctly, runs the action and
store the new response for the updated item. What I need to do is wrap all this
code in a plugin, namely smartly_caches that should be used as a replacement to
Rails’ caches_action so that you don’t have to write any of the above code in
your controller, nor do you have to write the model observer. A smart
implementation of cache_response should be included in the plugin that would
save a memcache access whenever possible by using http cache as a first level
cache. Ideally all you need to do is add the following line to your controller:
Yet, it would be even better if we can selectively update versions of
associated members of models. For example we may to want to expire the show
page of item 1 (items/1) not only when the item 1 changes, but also when the
price (which is a different model associated with the Item) of item 1 changes.
So, we want to be able to write something as easy as:
Smarter than ever, isn’t it?
Comments
Post a Comment
eSpace podcast Prodcast
Archive
Latest Comments
- zxdvcs Commented on Reading Arabic in a PuTTY Connection
- zxdvcs Commented on Reading Arabic in a PuTTY Connection
- Ed Hardy Commented on Check Out Our iGoogle Gadgets
- Ed Hardy Commented on Thin, the thin server that can!

