Class: Rack::Cache::MetaStore

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/cache/metastore.rb

Overview

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.

Direct Known Subclasses

Disk, Heap, MemCache

Defined Under Namespace

Classes: Disk, Heap, MemCache

Constant Summary collapse

HEAP =
Heap
MEM =
HEAP
DISK =
Disk
FILE =
Disk
MEMCACHE =
MemCache
MEMCACHED =
MemCache

Instance Method Summary collapse

Instance Method Details

#lookup(request, entity_store) ⇒ Object

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.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rack/cache/metastore.rb', line 27

def lookup(request, entity_store)
  entries = read(request.fullpath)

  # bail out if we have nothing cached
  return nil if entries.empty?

  # find a cached entry that matches the request.
  env = request.env
  match = entries.detect{|req,res| requests_match?(res['Vary'], env, req)}
  return nil if match.nil?

  req, res = match
  if body = entity_store.open(res['X-Content-Digest'])
    response = Rack::Cache::Response.new(res['X-Status'].to_i, res, body)
    response.activate!
    response
  else
    # TODO the metastore referenced an entity that doesn't exist in
    # the entitystore. we definitely want to return nil but we should
    # also purge the entry from the meta-store when this is detected.
  end
end

#store(request, response, entity_store) ⇒ Object

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. – TODO canonicalize URL key



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rack/cache/metastore.rb', line 55

def store(request, response, entity_store)
  key = request.fullpath
  stored_env = persist_request(request)

  # write the response body to the entity store if this is the
  # original response.
  response['X-Status'] = response.status.to_s
  if response['X-Content-Digest'].nil?
    digest, size = entity_store.write(response.body)
    response['X-Content-Digest'] = digest
    response['Content-Length'] = size.to_s unless response['Transfer-Encoding']
    response.body = entity_store.open(digest)
    response.activate!
  end

  # read existing cache entries, remove non-varying, and add this one to
  # the list
  vary = response.vary
  entries =
    read(key).reject do |env,res|
      (vary == res['Vary']) &&
        requests_match?(vary, env, stored_env)
    end
  entries.unshift [stored_env, {}.update(response.headers)]
  write key, entries
end