From 9a53093cf7c3eb34d7861f13bc9a53263b3625cf Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Tue, 25 Aug 2015 13:36:28 +0100 Subject: [PATCH 1/6] Documents use_native_ttl --- doc/configuration.markdown | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/configuration.markdown b/doc/configuration.markdown index 0925561..00eabd2 100644 --- a/doc/configuration.markdown +++ b/doc/configuration.markdown @@ -124,4 +124,13 @@ 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 the cache store. 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. + From fb529eff314b8ef6dd8a47f089722a205b9c0cce Mon Sep 17 00:00:00 2001 From: Mike Evans Date: Mon, 28 Oct 2013 12:26:19 -0400 Subject: [PATCH 2/6] Enabling native ttl option for metastore --- lib/rack/cache/meta_store.rb | 20 ++++++++++++-------- test/meta_store_test.rb | 6 ++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/rack/cache/meta_store.rb b/lib/rack/cache/meta_store.rb index 716dd27..7b8db4d 100644 --- a/lib/rack/cache/meta_store.rb +++ b/lib/rack/cache/meta_store.rb @@ -81,7 +81,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'] + write key, entries, response.ttl + else + write key, entries + end key end @@ -155,7 +159,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 @@ -188,7 +192,7 @@ def read(key) end end - def write(key, entries) + def write(key, entries, ttl = nil) @hash[key] = Marshal.dump(entries) end @@ -226,7 +230,7 @@ def read(key) [] end - def write(key, entries) + def write(key, entries, ttl = nil) tries = 0 begin path = key_path(key) @@ -325,9 +329,9 @@ def read(key) cache.get(key) || [] end - def write(key, entries) + def write(key, entries, ttl = 0) key = hexdigest(key) - cache.set(key, entries) + cache.set(key, entries, ttl) end def purge(key) @@ -359,9 +363,9 @@ def read(key) [] end - def write(key, entries) + def write(key, entries, ttl = 0) key = hexdigest(key) - cache.set(key, entries) + cache.set(key, entries, ttl) end def purge(key) diff --git a/test/meta_store_test.rb b/test/meta_store_test.rb index f2b3fc2..be2a936 100644 --- a/test/meta_store_test.rb +++ b/test/meta_store_test.rb @@ -253,6 +253,12 @@ def purge(*args); nil end @store.read(key).length.must_equal 2 end + + it 'takes a ttl parameter for #write' do + @store.write('/test', [[{},{}],[{},{}]], 0) + tuples = @store.read('/test') + tuples.must_equal [ [{},{}], [{},{}] ] + end end end end From dc587dd6c5fe17bb26e26817602dbb94f2b23447 Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Thu, 27 Aug 2015 17:52:47 +0100 Subject: [PATCH 3/6] Passes only valid ttls to the metastore --- lib/rack/cache/meta_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rack/cache/meta_store.rb b/lib/rack/cache/meta_store.rb index 7b8db4d..2134b27 100644 --- a/lib/rack/cache/meta_store.rb +++ b/lib/rack/cache/meta_store.rb @@ -81,7 +81,7 @@ def store(request, response, entity_store) headers.delete 'Age' entries.unshift [stored_env, headers] - if request.env['rack-cache.use_native_ttl'] + if request.env['rack-cache.use_native_ttl'] && response.fresh? write key, entries, response.ttl else write key, entries From b2ed0a78d4c9d99ff376118c2f68c344ae06ff95 Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Fri, 19 Feb 2016 11:32:47 +0100 Subject: [PATCH 4/6] Clarifies use_native_ttl docs --- doc/configuration.markdown | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/configuration.markdown b/doc/configuration.markdown index 00eabd2..5db4793 100644 --- a/doc/configuration.markdown +++ b/doc/configuration.markdown @@ -127,9 +127,10 @@ For more options see the [Rack::Request documentation](http://rack.rubyforge.org ### `use_native_ttl` -Passes on the expiration timestamp to the cache store. 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. +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. From aeb250da6058f4b04fb405e7fdd016a416e12558 Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Fri, 19 Feb 2016 11:33:07 +0100 Subject: [PATCH 5/6] Clarifies TTL usage for Memcache --- lib/rack/cache/meta_store.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rack/cache/meta_store.rb b/lib/rack/cache/meta_store.rb index 2134b27..e3ca8d2 100644 --- a/lib/rack/cache/meta_store.rb +++ b/lib/rack/cache/meta_store.rb @@ -329,6 +329,7 @@ def read(key) cache.get(key) || [] end + # Default TTL to zero, interpreted as "don't expire" by Memcached. def write(key, entries, ttl = 0) key = hexdigest(key) cache.set(key, entries, ttl) @@ -363,6 +364,7 @@ def read(key) [] end + # Default TTL to zero, interpreted as "don't expire" by Memcached. def write(key, entries, ttl = 0) key = hexdigest(key) cache.set(key, entries, ttl) From 3caa6f9da36b09573128cb2b45c5016813705a7e Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Fri, 19 Feb 2016 11:33:33 +0100 Subject: [PATCH 6/6] Adds test coverage for use_native_ttl --- test/meta_store_test.rb | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/test/meta_store_test.rb b/test/meta_store_test.rb index be2a936..3498997 100644 --- a/test/meta_store_test.rb +++ b/test/meta_store_test.rb @@ -114,6 +114,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 @@ -254,10 +260,30 @@ def purge(*args); nil end @store.read(key).length.must_equal 2 end - it 'takes a ttl parameter for #write' do - @store.write('/test', [[{},{}],[{},{}]], 0) - tuples = @store.read('/test') - tuples.must_equal [ [{},{}], [{},{}] ] + # 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