Skip to content

Commit 0dfbd63

Browse files
committed
Merge pull request #117 from mezis/fixes
Metastore TTL support
2 parents ec3f599 + 3caa6f9 commit 0dfbd63

3 files changed

Lines changed: 57 additions & 9 deletions

File tree

doc/configuration.markdown

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,14 @@ which will act as the cache key generator:
124124
end
125125

126126
For more options see the [Rack::Request documentation](http://rack.rubyforge.org/doc/classes/Rack/Request.html)
127-
127+
128+
### `use_native_ttl`
129+
130+
Passes on the expiration timestamp to cache stores that support it, like
131+
Memcache and Redis. This may be necessary with some stores to keep them from
132+
filling up, e.g. if using a Redis backend and the `volatile-ttl` expiration
133+
policy.
134+
135+
If using `memcached`, it will speed up misses slightly as the middleware won't
136+
need to fetch metadata and check timestamps.
137+

lib/rack/cache/meta_store.rb

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ def store(request, response, entity_store)
9191
headers.delete 'Age'
9292

9393
entries.unshift [stored_env, headers]
94-
write key, entries
94+
if request.env['rack-cache.use_native_ttl'] && response.fresh?
95+
write key, entries, response.ttl
96+
else
97+
write key, entries
98+
end
9599
key
96100
end
97101

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

@@ -198,7 +202,7 @@ def read(key)
198202
end
199203
end
200204

201-
def write(key, entries)
205+
def write(key, entries, ttl = nil)
202206
@hash[key] = Marshal.dump(entries)
203207
end
204208

@@ -236,7 +240,7 @@ def read(key)
236240
[]
237241
end
238242

239-
def write(key, entries)
243+
def write(key, entries, ttl = nil)
240244
tries = 0
241245
begin
242246
path = key_path(key)
@@ -335,9 +339,10 @@ def read(key)
335339
cache.get(key) || []
336340
end
337341

338-
def write(key, entries)
342+
# Default TTL to zero, interpreted as "don't expire" by Memcached.
343+
def write(key, entries, ttl = 0)
339344
key = hexdigest(key)
340-
cache.set(key, entries)
345+
cache.set(key, entries, ttl)
341346
end
342347

343348
def purge(key)
@@ -369,9 +374,10 @@ def read(key)
369374
[]
370375
end
371376

372-
def write(key, entries)
377+
# Default TTL to zero, interpreted as "don't expire" by Memcached.
378+
def write(key, entries, ttl = 0)
373379
key = hexdigest(key)
374-
cache.set(key, entries)
380+
cache.set(key, entries, ttl)
375381
end
376382

377383
def purge(key)

test/meta_store_test.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ def self.call(request); request.path_info.reverse end
116116
store_simple_entry('/bad', { 'SOME_THING' => Proc.new {} })
117117
end
118118

119+
it 'supports a ttl parameter for #write' do
120+
@store.write('/test', [[{},{}],[{},{}]], 0)
121+
tuples = @store.read('/test')
122+
tuples.must_equal [ [{},{}], [{},{}] ]
123+
end
124+
119125
# Abstract methods ===========================================================
120126

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

271277
@store.read(key).length.must_equal 2
272278
end
279+
280+
# TTL ====================================================================
281+
282+
context 'logging writes' do
283+
write_intercept = Module.new do
284+
attr_reader :last_write
285+
286+
def write(*args)
287+
@last_write = args
288+
super
289+
end
290+
end
291+
292+
before do
293+
@entity_store.extend(write_intercept)
294+
@store.extend(write_intercept)
295+
end
296+
297+
it 'passes a TTL to the stores is use_native_ttl is truthy' do
298+
req1 = mock_request('/test', { 'rack-cache.use_native_ttl' => true })
299+
res1 = mock_response(200, {'Cache-Control' => 'max-age=42'}, ['foo'])
300+
@store.store(req1, res1, @entity_store)
301+
@entity_store.last_write.must_equal [['foo'], 42]
302+
@store.last_write[2].must_equal 42
303+
end
304+
end
273305
end
274306
end
275307
end

0 commit comments

Comments
 (0)