Class Rack::Cache::MetaStore

  1. lib/rack/cache/metastore.rb
Parent: Object

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 read, write, and purge methods. Care has been taken to keep these low-level methods dumb and straight-forward to implement.

Methods

public instance

  1. cache_key
  2. invalidate
  3. lookup
  4. store

protected instance

  1. purge
  2. read
  3. write

Constants

HEAP = Heap
MEM = HEAP
DISK = Disk
FILE = Disk
MEMCACHE = if defined?(::Memcached)

Public instance methods

cache_key (request)

Generate a cache key for the request.

[show source]
    # File lib/rack/cache/metastore.rb, line 83
83:     def cache_key(request)
84:       keygen = request.env['rack-cache.cache_key'] || Key
85:       keygen.call(request)
86:     end
invalidate (request, entity_store)

Invalidate all cache entries that match the request.

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

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.

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

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 write with the new list of cache entries.

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

Protected instance methods

purge (key)

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

[show source]
     # File lib/rack/cache/metastore.rb, line 158
158:     def purge(key)
159:       raise NotImplemented
160:     end
read (key)

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.

[show source]
     # File lib/rack/cache/metastore.rb, line 145
145:     def read(key)
146:       raise NotImplemented
147:     end
write (key, negotiations)

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.

[show source]
     # File lib/rack/cache/metastore.rb, line 152
152:     def write(key, negotiations)
153:       raise NotImplemented
154:     end