Parent

Rack::Cache::MetaStore

The MetaStore is responsible for storing meta information about a request/response pair keyed by the request’s URL.

The meta store keeps a list of request/response pairs for each canonical request URL. A request/response pair is a two element Array of the form:

  [request, response]

The request element is a Hash of Rack environment keys. Only protocol keys (i.e., those that start with “HTTP_”) are stored. The response element is a Hash of cached HTTP response headers for the paired request.

The MetaStore class is abstract and should not be instanstiated directly. Concrete subclasses should implement the protected #, #, and # methods. Care has been taken to keep these low-level methods dumb and straight-forward to implement.

Constants

HEAP
MEM
DISK
FILE
MEMCACHE
MEMCACHED
GAECACHE
GAE

Public Instance Methods

cache_key(request) click to toggle source

Generate a cache key for the request.

    # File lib/rack/cache/metastore.rb, line 88
88:     def cache_key(request)
89:       keygen = request.env['rack-cache.cache_key'] || Key
90:       keygen.call(request)
91:     end
invalidate(request, entity_store) click to toggle source

Invalidate all cache entries that match the request.

     # File lib/rack/cache/metastore.rb, line 94
 94:     def invalidate(request, entity_store)
 95:       modified = false
 96:       key = cache_key(request)
 97:       entries =
 98:         read(key).map do |req, res|
 99:           response = restore_response(res)
100:           if response.fresh?
101:             response.expire!
102:             modified = true
103:             [req, persist_response(response)]
104:           else
105:             [req, res]
106:           end
107:         end
108:       write key, entries if modified
109:     end
lookup(request, entity_store) click to toggle source

Locate a cached response for the request provided. Returns a Rack::Cache::Response object if the cache hits or nil if no cache entry was found.

    # File lib/rack/cache/metastore.rb, line 28
28:     def lookup(request, entity_store)
29:       key = cache_key(request)
30:       entries = read(key)
31: 
32:       # bail out if we have nothing cached
33:       return nil if entries.empty?
34: 
35:       # find a cached entry that matches the request.
36:       env = request.env
37:       match = entries.detect{|req,res| requests_match?(res['Vary'], env, req)}
38:       return nil if match.nil?
39: 
40:       _, res = match
41:       if body = entity_store.open(res['X-Content-Digest'])
42:         restore_response(res, body)
43:       else
44:         # TODO the metastore referenced an entity that doesn't exist in
45:         # the entitystore. we definitely want to return nil but we should
46:         # also purge the entry from the meta-store when this is detected.
47:       end
48:     end
store(request, response, entity_store) click to toggle source

Write a cache entry to the store under the given key. Existing entries are read and any that match the response are removed. This method calls # with the new list of cache entries.

    # File lib/rack/cache/metastore.rb, line 53
53:     def store(request, response, entity_store)
54:       key = cache_key(request)
55:       stored_env = persist_request(request)
56: 
57:       # write the response body to the entity store if this is the
58:       # original response.
59:       if response.headers['X-Content-Digest'].nil?
60:         if request.env['rack-cache.use_native_ttl'] && response.fresh?
61:           digest, size = entity_store.write(response.body, response.ttl)
62:         else
63:           digest, size = entity_store.write(response.body)
64:         end
65:         response.headers['X-Content-Digest'] = digest
66:         response.headers['Content-Length'] = size.to_s unless response.headers['Transfer-Encoding']
67:         response.body = entity_store.open(digest)
68:       end
69: 
70:       # read existing cache entries, remove non-varying, and add this one to
71:       # the list
72:       vary = response.vary
73:       entries =
74:         read(key).reject do |env,res|
75:           (vary == res['Vary']) &&
76:             requests_match?(vary, env, stored_env)
77:         end
78: 
79:       headers = persist_response(response)
80:       headers.delete 'Age'
81: 
82:       entries.unshift [stored_env, headers]
83:       write key, entries
84:       key
85:     end

Protected Instance Methods

purge(key) click to toggle source

Remove all cached entries at the key specified. No error is raised when the key does not exist.

     # File lib/rack/cache/metastore.rb, line 163
163:     def purge(key)
164:       raise NotImplemented
165:     end
read(key) click to toggle source

Locate all cached request/response pairs that match the specified URL key. The result must be an Array of all cached request/response pairs. An empty Array must be returned if nothing is cached for the specified key.

     # File lib/rack/cache/metastore.rb, line 150
150:     def read(key)
151:       raise NotImplemented
152:     end
write(key, negotiations) click to toggle source

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.

     # File lib/rack/cache/metastore.rb, line 157
157:     def write(key, negotiations)
158:       raise NotImplemented
159:     end

Private Instance Methods

hexdigest(data) click to toggle source

Generate a SHA1 hex digest for the specified string. This is a simple utility method for meta store implementations.

     # File lib/rack/cache/metastore.rb, line 170
170:     def hexdigest(data)
171:       Digest::SHA1.hexdigest(data)
172:     end
persist_request(request) click to toggle source

Extract the environment Hash from request while making any necessary modifications in preparation for persistence. The Hash returned must be marshalable.

     # File lib/rack/cache/metastore.rb, line 116
116:     def persist_request(request)
117:       env = request.env.dup
118:       env.reject! { |key,val| key =~ /[^0-9A-Z_]/ || !val.respond_to?(:to_str) }
119:       env
120:     end
persist_response(response) click to toggle source
     # File lib/rack/cache/metastore.rb, line 129
129:     def persist_response(response)
130:       hash = response.headers.to_hash
131:       hash['X-Status'] = response.status.to_s
132:       hash
133:     end
requests_match?(vary, env1, env2) click to toggle source

Determine whether the two environment hashes are non-varying based on the vary response header value provided.

     # File lib/rack/cache/metastore.rb, line 137
137:     def requests_match?(vary, env1, env2)
138:       return true if vary.nil? || vary == ''
139:       vary.split(/[\s,]+/).all? do |header|
140:         key = "HTTP_#{header.upcase.tr('-', '_')}"
141:         env1[key] == env2[key]
142:       end
143:     end
restore_response(hash, body=nil) click to toggle source

Converts a stored response hash into a Response object. The caller is responsible for loading and passing the body if needed.

     # File lib/rack/cache/metastore.rb, line 124
124:     def restore_response(hash, body=nil)
125:       status = hash.delete('X-Status').to_i
126:       Rack::Cache::Response.new(status, hash, body)
127:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.