smartly_caches, smarter than ever
1
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
Archive
Latest Comments
- Fizo Commented on Ruby Fibers Vs Ruby Threads
- Michael Commented on IE6 Background Image Problem
- chrisb Commented on IE6 Background Image Problem
- Mohamed Shatla Commented on Egypt Wins UK's National Outsourcing Association Award
- Youssef Commented on Egypt Wins UK's National Outsourcing Association Award

