Skip to content

Commit

Permalink
Merge pull request #117 from mezis/fixes
Browse files Browse the repository at this point in the history
Metastore TTL support
  • Loading branch information
grosser committed Feb 21, 2016
2 parents ec3f599 + 3caa6f9 commit 0dfbd63
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 9 deletions.
12 changes: 11 additions & 1 deletion doc/configuration.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,14 @@ which will act as the cache key generator:
end

For more options see the [Rack::Request documentation](http://rack.rubyforge.org/doc/classes/Rack/Request.html)


### `use_native_ttl`

Passes on the expiration timestamp to cache stores that support it, like
Memcache and Redis. This may be necessary with some stores to keep them from
filling up, e.g. if using a Redis backend and the `volatile-ttl` expiration
policy.

If using `memcached`, it will speed up misses slightly as the middleware won't
need to fetch metadata and check timestamps.

22 changes: 14 additions & 8 deletions lib/rack/cache/meta_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ def store(request, response, entity_store)
headers.delete 'Age'

entries.unshift [stored_env, headers]
write key, entries
if request.env['rack-cache.use_native_ttl'] && response.fresh?
write key, entries, response.ttl
else
write key, entries
end
key
end

Expand Down Expand Up @@ -165,7 +169,7 @@ def read(key)
# Store an Array of request/response pairs for the given key. Concrete
# implementations should not attempt to filter or concatenate the
# list in any way.
def write(key, negotiations)
def write(key, negotiations, ttl = nil)
raise NotImplementedError
end

Expand Down Expand Up @@ -198,7 +202,7 @@ def read(key)
end
end

def write(key, entries)
def write(key, entries, ttl = nil)
@hash[key] = Marshal.dump(entries)
end

Expand Down Expand Up @@ -236,7 +240,7 @@ def read(key)
[]
end

def write(key, entries)
def write(key, entries, ttl = nil)
tries = 0
begin
path = key_path(key)
Expand Down Expand Up @@ -335,9 +339,10 @@ def read(key)
cache.get(key) || []
end

def write(key, entries)
# Default TTL to zero, interpreted as "don't expire" by Memcached.
def write(key, entries, ttl = 0)
key = hexdigest(key)
cache.set(key, entries)
cache.set(key, entries, ttl)
end

def purge(key)
Expand Down Expand Up @@ -369,9 +374,10 @@ def read(key)
[]
end

def write(key, entries)
# Default TTL to zero, interpreted as "don't expire" by Memcached.
def write(key, entries, ttl = 0)
key = hexdigest(key)
cache.set(key, entries)
cache.set(key, entries, ttl)
end

def purge(key)
Expand Down
32 changes: 32 additions & 0 deletions test/meta_store_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ def self.call(request); request.path_info.reverse end
store_simple_entry('/bad', { 'SOME_THING' => Proc.new {} })
end

it 'supports a ttl parameter for #write' do
@store.write('/test', [[{},{}],[{},{}]], 0)
tuples = @store.read('/test')
tuples.must_equal [ [{},{}], [{},{}] ]
end

# Abstract methods ===========================================================

it 'stores a cache entry' do
Expand Down Expand Up @@ -270,6 +276,32 @@ def purge(*args); nil end

@store.read(key).length.must_equal 2
end

# TTL ====================================================================

context 'logging writes' do
write_intercept = Module.new do
attr_reader :last_write

def write(*args)
@last_write = args
super
end
end

before do
@entity_store.extend(write_intercept)
@store.extend(write_intercept)
end

it 'passes a TTL to the stores is use_native_ttl is truthy' do
req1 = mock_request('/test', { 'rack-cache.use_native_ttl' => true })
res1 = mock_response(200, {'Cache-Control' => 'max-age=42'}, ['foo'])
@store.store(req1, res1, @entity_store)
@entity_store.last_write.must_equal [['foo'], 42]
@store.last_write[2].must_equal 42
end
end
end
end
end
Expand Down

0 comments on commit 0dfbd63

Please sign in to comment.