Class: Rack::Client::Cache::MetaStore

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

Direct Known Subclasses

Heap

Defined Under Namespace

Classes: Heap

Constant Summary collapse

HEAP =
Heap
MEM =
HEAP

Instance Method Summary collapse

Instance Method Details

#cache_key(request) ⇒ Object



61
62
63
64
# File 'lib/rack/client/middleware/cache/metastore.rb', line 61

def cache_key(request)
  keygen = request.env['rack-client-cache.cache_key'] || Key
  keygen.call(request)
end

#lookup(request, entity_store) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rack/client/middleware/cache/metastore.rb', line 6

def lookup(request, entity_store)
  key = cache_key(request)
  entries = read(key)

  # 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'])
    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
    # also purge the entry from the meta-store when this is detected.
  end
end

#persist_request(request) ⇒ Object

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



69
70
71
72
73
# File 'lib/rack/client/middleware/cache/metastore.rb', line 69

def persist_request(request)
  env = request.env.dup
  env.reject! { |key,val| key =~ /[^0-9A-Z_]/ }
  env
end

#persist_response(response) ⇒ Object



75
76
77
78
79
# File 'lib/rack/client/middleware/cache/metastore.rb', line 75

def persist_response(response)
  hash = response.headers.to_hash
  hash['X-Status'] = response.status.to_s
  hash
end

#requests_match?(vary, env1, env2) ⇒ Boolean

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

Returns:

  • (Boolean)


90
91
92
93
94
95
96
# File 'lib/rack/client/middleware/cache/metastore.rb', line 90

def requests_match?(vary, env1, env2)
  return true if vary.nil? || vary == ''
  vary.split(/[\s,]+/).all? do |header|
    key = "HTTP_#{header.upcase.tr('-', '_')}"
    env1[key] == env2[key]
  end
end

#restore_response(hash, body = nil) ⇒ Object

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



83
84
85
86
# File 'lib/rack/client/middleware/cache/metastore.rb', line 83

def restore_response(hash, body=nil)
  status = hash.delete('X-Status').to_i
  Rack::Client::Cache::Response.new(status, hash, body)
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.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rack/client/middleware/cache/metastore.rb', line 31

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

  # write the response body to the entity store if this is the
  # original response.
  if response.headers['X-Content-Digest'].nil?
    digest, size = entity_store.write(response.body)
    response.headers['X-Content-Digest'] = digest
    response.headers['Content-Length'] = size.to_s unless response.headers['Transfer-Encoding']
    response.body = entity_store.open(digest)
  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

  headers = persist_response(response)
  headers.delete 'Age'

  entries.unshift [stored_env, headers]
  write key, entries
  key
end