Don’t bother looking for carrots, we’re just going to talk about caching in Camping.
In the perfect world we would let the webserver serve static files. Believe me, sysadmins like static and they will go to great lengths to convince you. They will even pull statistics out of long forgotten orifices. It will contain many milliseconds.
If most of your content is (semi-)static this isn’t a very outrageous demand, but we’re out camping. Everybody knowns that you have to rough it a little bit when you’re camping. You have to be prepared to pick up your beloved small polyester housing and relocate. Always.
Camping doesn’t sit on a 404 handler but has to take care of all the incoming requests, so we can’t just dump some files in the document root and hope never to hear from the request again. We have to be smarter! Let’s look at what I just found in my subversion repository.
Apparently somebody is setting a ROOT contant here. Looks like the directory where the camping application is located. You will have to make sure ROOT points to a sensible location for your own application though.
ROOT = File.expand_path(File.dirname(__FILE__))
module Cushion
include PageCaching
end
Hmm, caching must take place in the controller because we just determined that we can’t do it before the request.
class PostView < R '/(\d+)'
def get(id)
cached do
@post = Post.find id
render :post_view
end
end
end
Ok, so the cached method appears to take a block and caches it’s return value. But how do they control headers in the fictional world where weblogs would return JSON?
class PostAsJSON < R '/(\d+)/'
def get(id)
@headers['Content-Type'] = 'text/javascript; charset=utf-8'
cached do
Post.find(id).to_json
end
end
end
That’s smart. Placing it just before the cache mechanism makes sure that the code is always executed, even when the cache doesn’t have to be generated.
But now that we have all this stuff in the cache, how can we ever get rid of it? Fear not my friends, we just sweep it away!
class AdminPostAdd < R '/admin/post/add'
def post
@post = Post.new input.post
@post.user = User.find_by_username(@username)
if @post.save
sweep
redirect AdminPost
else
render :admin_post_add
end
end
end
And it even proved to be a little bit quicker.
| Before | Request rate: 16.7 req/s (59.8 ms/req) |
| After | Request rate: 400.0 req/s (2.5 ms/req) |
I know this is an extremely simple solution, but I think I like it. If you like it too you can find it in the Cushion repository in lib/page_caching.rb.