Skip to content

Commit

Permalink
Implmented a cache store thats tougher than tonka
Browse files Browse the repository at this point in the history
  • Loading branch information
benschwarz committed Jun 21, 2008
1 parent 35955ba commit ac463de
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 12 deletions.
17 changes: 11 additions & 6 deletions lib/merb-cache/cache_stores/mintcache_store.rb
Expand Up @@ -17,16 +17,17 @@ def initialize(config)
end

def get(key)
data = @memcache.get key
if data.nil?
mint_cache = @memcached.get_multi "#{key}_validity", "#{key}_data"
begin
data = @memcache.get(key)
rescue Memcached::NotFound
mint_cache = @memcache.get(["#{key}_validity", "#{key}_data"])
validity_time, data = mint_cache["#{key}_validity"], mint_cache["#{key}_data"]

if !validity_time.nil? and Time.now > validity_time
Merb.logger.info("stale cache, refreshing")
# Cache to be set for 60 seconds while its regenerated for the
# poor soul who gets a cache miss
@memcache.set key, data, 60
@memcache.set(key, data, 60)
data = nil
end
end
Expand All @@ -52,11 +53,15 @@ def put (key, value, expiry = nil)
end

def expire!(key)
@memcache.delete key
[key, "#{key}_validity", "#{key}_data"].each{|k| @memcache.delete(k) }
end

# Still use @memcached because we want to reset the cache
# after the first level misses
def cached?(key)
!get(key).nil?
!@memcache.get(key).nil?
rescue Memcached::NotFound
return false
end

private
Expand Down
48 changes: 42 additions & 6 deletions spec/mintcache_store_spec.rb
Expand Up @@ -38,7 +38,7 @@
it "should expire a key" do
@store.get('key').should eql "stored_data"
@store.expire!('key')
@store.get('key').should be_nil
@store.cached?('key').should be_false
end

it "should know when there isn't a cache" do
Expand All @@ -47,9 +47,45 @@
end

describe "mintache store avoiding the dogpile effect" do
it "should store a second key to keep check of the time" # "#{key}_validity"
it "should store a third key to keep the data for a longer expiry time" # "#{key}_data"
it "should use the second and third keys to return the data if the first key has expired"
it "should return a cache miss when the second level cache is used"
it "should set a temporary cache when the second level cache is used"
before :all do
@store = Merb::Cache::MintcachedStore.new({:host => "127.0.0.1:11211"})
end

it "should store a second key to keep check of the time" do
@store.put("key", "data", 10)
@store.get("key_validity").should_not be_nil
end

it "should store the validity key for double the amount of time of the initial expiry" do
pending "Need a brain to write this"
@store.put("expiry_key_spec", "data", 1)
expiry_time = @store.get("expiry_key_spec_validity")
(expiry_time).should eql "120"
end

it "should store a third key to keep the data for a longer expiry time" do
@store.put("key", "data", 10)
@store.get("key_data").should_not be_nil
end

it "should return a cache miss when the second level cache is used" do
@store.put("short_key", "data", 1)
sleep 1
@store.cached?("short_key").should be_false
end

it "should store a backup key to avoid cache misses" do
@store.put("short_key", "data", 1)
sleep 1
@store.get("short_key").should be_nil
@store.get("short_key").should eql "data"
end

it "should expire all additional keys when expire is called" do
@store.put("key", "data", 1)
@store.expire!("key")
@store.get("key").should be_nil
@store.get("key_validity").should be_nil
@store.get("key_data").should be_nil
end
end

0 comments on commit ac463de

Please sign in to comment.