I really like the the acts_as_cached interface for model caching, but there are a few models that we wanted to cache in the process memory, but still maintain expiration functionality. We came up with this:
class InMemoryCacheStore < Hash
def initialize(options={})
@expire_entries = options[:expire_entries]
end
def set(key, data, ttl = nil)
if @expire_entries && ttl
self[key] = Entry.new(data.dup, Time.now.to_i + ttl) rescue data
else
self[key] = Entry.new(data.dup, nil) rescue data
end
end
def get(key)
r = self[key]
if @expire_entries && r && r.expires_at < Time.now.to_i
self.delete(key)
r = nil
end
r ? r.obj : nil
end
private
class Entry
attr_accessor :obj attr_accessor :expires_at
def initialize(obj, expires_at)
@obj = obj
@expires_at = expires_at
end
end
end
Example without expiration:
class SomeModel < ActiveRecord::Base
acts_as_cached :store => InMemoryCacheStore.new
end
Example with expiration:
class SomeModel < ActiveRecord::Base
acts_as_cached :store => InMemoryCacheStore.new(:expire_entires => true)
def self.ttl
24.hours
end
end
Performance for 1000 lookups:
db on localhost: 1.52 secs
memcached on localhost: 0.78 secs
InMemoryCacheStore: 0.345 secs
No comments:
Post a Comment