|
This post originated from an RSS feed registered with Ruby Buzz
by Jonathan Weiss.
|
Original Post: Time-based Fragment Caching with MemCache
Feed Title: BlogFish
Feed URL: http://blog.innerewut.de/feed/atom.xml
Feed Description: Weblog by Jonathan Weiss about Unix, BSD, security, Programming in Ruby, Ruby on Rails and Agile Development.
|
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Jonathan Weiss
Latest Posts From BlogFish
|
|
For the sidebar content in MeinProf.de we use fragment caching. One problem with caching is that expiring entries can get really messy. Time-based caching can solve this problem but the current caching implementation in Rails does not support this.
While poking around in the MemCache-client implementation from the Robotcoop I saw that MemCache itself does support time-based expiry of cached entries. Thanks to Ruby I just re-implemented the write method in ActionController::Caching::Fragments::MemCacheStore so that we could expire our entries after some given time:
class ActionController::Caching::Fragments::MemCacheStore
def write(name, value, options=nil)
@data.set(name, value, 30.minutes)
end
end
Now all fragments expire after 30 minutes. If you want to have different live-times for your caches you have to distinct by the name of the fragment. Normally fragments created with the <% cache do %> call in views are named after the controller and action, e.g. controller/actionname. You can also specify a name like <% cache("UniPage_#{uni.id}") do %>.
class ActionController::Caching::Fragments::MemCacheStore
def write(name, value, options=nil)
if name =~ %r{^UniPage}
@data.set(name, value, 30.minutes)
elsif name == "mycontroller/myaction"
@data.set(name, value, 45.minutes)
else
@data.set(name, value, 60.minutes)
end
end
end
Not the cleanest solution but it works very well for us.
If you want to also save your sessions in MemCache with the memcache-client library from the Robotcoop, add this code to ActionController::Caching::Fragments::MemCacheStore:
class ActionController::Caching::Fragments::MemCacheStore
def data=(cache)
@data = cache
end
end
In summary our code in config/environments/production.rb looks like this:
### MemCached Server ###
CACHE = MemCache.new :c_threshold => 10_000, :compression => true,\
:debug => false, :namespace => 'meinprof_de', :readonly => false, :urlencode => false
CACHE.servers = '127.0.0.1:11211'
### Sessions in MemCached ###
session_options = {
:database_manager => CGI::Session::MemCacheStore,
:cache => CACHE
}
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update session_options
### FragmentCaching im MemCached ###
# Allow us to set the CACHE as the Fragment Cache store
class ActionController::Caching::Fragments::MemCacheStore
def data=(cache)
@data = cache
end
def write(name, value, options=nil)
if name =~ %r{^Random_TopFlop}
@data.set(name, value, 30.minutes)
elsif name =~ %r{^RegionPage}
@data.set(name, value, 60.minutes)
elsif name =~ %r{^UniPage}
@data.set(name, value, 60.minutes)
else
@data.set(name, value, 120.minutes)
end
end
end
ActionController::Base.fragment_cache_store = :mem_cache_store ,{}
ActionController::Base.fragment_cache_store.data = CACHE
Read: Time-based Fragment Caching with MemCache