Permalink
Browse files

Make invalidating responses at the metastore a bit cleaner

  • Loading branch information...
1 parent 362aed3 commit 3ebd1a33f438ab1838b5d62287bfda4d090ab072 @rtomayko rtomayko committed Mar 8, 2009
Showing with 47 additions and 7 deletions.
  1. +6 −0 lib/rack/cache/headers.rb
  2. +18 −7 lib/rack/cache/metastore.rb
  3. +23 −0 test/headers_test.rb
@@ -83,6 +83,12 @@ def must_revalidate?
cache_control.must_revalidate || cache_control.proxy_revalidate
end
+ # Mark the response stale by setting the Age header to be equal to the
+ # maximum age of the response.
+ def expire!
+ headers['Age'] = max_age.to_s if fresh?
+ end
+
# The date, as specified by the Date header. When no Date header is present,
# set the Date header to Time.now and return.
def date
@@ -38,9 +38,7 @@ def lookup(request, entity_store)
req, res = match
if body = entity_store.open(res['X-Content-Digest'])
- status = res.delete('X-Status').to_i
- response = Rack::Cache::Response.new(status, res, body)
- response
+ restore_response(res, body)
else
# TODO the metastore referenced an entity that doesn't exist in
# the entitystore. we definitely want to return nil but we should
@@ -73,7 +71,7 @@ def store(request, response, entity_store)
requests_match?(vary, env, stored_env)
end
- headers = {'X-Status' => response.status.to_s}.update(response.headers)
+ headers = persist_response(response)
headers.delete 'Age'
entries.unshift [stored_env, headers]
@@ -93,11 +91,11 @@ def invalidate(request, entity_store)
key = cache_key(request)
entries =
read(key).map do |req, res|
- response = Rack::Cache::Response.new(0, res, nil) # XXX
+ response = restore_response(res)
if response.fresh?
- response.headers['Age'] = (response.max_age + 1).to_s
+ response.expire!
modified = true
- [req, response.headers.to_hash]
+ [req, persist_response(response)]
else
[req, res]
end
@@ -116,6 +114,19 @@ def persist_request(request)
env
end
+ # Converts a stored response hash into a Response object. The caller
+ # is responsible for loading and passing the body if needed.
+ def restore_response(hash, body=nil)
+ status = hash.delete('X-Status').to_i
+ Rack::Cache::Response.new(status, hash, body)
+ end
+
+ def persist_response(response)
+ hash = response.headers.to_hash
+ hash['X-Status'] = response.status.to_s
+ hash
+ end
+
# Determine whether the two environment hashes are non-varying based on
# the vary response header value provided.
def requests_match?(vary, env1, env2)
View
@@ -107,6 +107,29 @@ def initialize(*args)
end
end
+ describe '#expire!' do
+ it 'sets the Age to be equal to the max-age' do
+ @res.headers['Cache-Control'] = 'max-age=100'
+ @res.expire!
+ @res.headers['Age'].should.equal '100'
+ end
+ it 'sets the Age to be equal to the s-maxage when both max-age and s-maxage present' do
+ @res.headers['Cache-Control'] = 'max-age=100, s-maxage=500'
+ @res.expire!
+ @res.headers['Age'].should.equal '500'
+ end
+ it 'does nothing when the response is already stale/expired' do
+ @res.headers['Cache-Control'] = 'max-age=5, s-maxage=500'
+ @res.headers['Age'] = '1000'
+ @res.expire!
+ @res.headers['Age'].should.equal '1000'
+ end
+ it 'does nothing when the response does not include freshness information' do
+ @res.expire!
+ @res.headers.should.not.include 'Age'
+ end
+ end
+
describe '#ttl' do
it 'is nil when no Expires or Cache-Control headers present' do
@res.ttl.should.be.nil

0 comments on commit 3ebd1a3

Please sign in to comment.