Class: Billy::Cache

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/billy/cache.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCache

Returns a new instance of Cache.



13
14
15
# File 'lib/billy/cache.rb', line 13

def initialize
  reset
end

Instance Attribute Details

#scopeObject

Returns the value of attribute scope.



11
12
13
# File 'lib/billy/cache.rb', line 11

def scope
  @scope
end

Instance Method Details

#cache_file(key) ⇒ Object



120
121
122
123
124
125
126
127
128
# File 'lib/billy/cache.rb', line 120

def cache_file(key)
  file = File.join(Billy.config.cache_path, "#{key}.yml")

  if File.symlink? file
    file = File.readlink file
  end

  file
end

#cached?(method, url, body) ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
20
21
# File 'lib/billy/cache.rb', line 17

def cached?(method, url, body)
  # Only log the key the first time it's looked up (in this method)
  key = key(method, url, body, true)
  !@cache[key].nil? || persisted?(key)
end

#fetch(method, url, body) ⇒ Object



27
28
29
30
# File 'lib/billy/cache.rb', line 27

def fetch(method, url, body)
  key = key(method, url, body)
  @cache[key] || fetch_from_persistence(key)
end

#fetch_from_persistence(key) ⇒ Object



32
33
34
35
36
37
# File 'lib/billy/cache.rb', line 32

def fetch_from_persistence(key)
  @cache[key] = YAML.load_file(cache_file(key)) if persisted?(key)
rescue ArgumentError => e
  Billy.log :error, "Could not parse YAML: #{e.message}"
  nil
end

#format_url(url, ignore_params = false, dynamic_jsonp = Billy.config.dynamic_jsonp) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/billy/cache.rb', line 96

def format_url(url, ignore_params = false, dynamic_jsonp = Billy.config.dynamic_jsonp)
  url = Addressable::URI.parse(url)
  port_to_include = Billy.config.ignore_cache_port ? '' : ":#{url.port}"
  formatted_url = url.scheme + '://' + url.host + port_to_include + url.path

  return formatted_url if ignore_params

  if url.query
    query_string = if dynamic_jsonp
                     query_hash = Rack::Utils.parse_query(url.query)
                     Billy.config.dynamic_jsonp_keys.each { |k| query_hash.delete(k) }
                     Rack::Utils.build_query(query_hash)
                   else
                     url.query
                   end

    formatted_url += "?#{query_string}"
  end

  formatted_url += '#' + url.fragment if url.fragment

  formatted_url
end

#key(method, orig_url, body, log_key = false) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/billy/cache.rb', line 71

def key(method, orig_url, body, log_key = false)
  if Billy.config.use_ignore_params
    ignore_params = Billy.config.ignore_params.include?(format_url(orig_url, true))
  else
    ignore_params = !Billy.config.allow_params.include?(format_url(orig_url, true))
  end
  merge_cached_response_key = _merge_cached_response_key(orig_url)
  url = Addressable::URI.parse(format_url(orig_url, ignore_params))
  key = if merge_cached_response_key
          method + '_' + Digest::SHA1.hexdigest(scope.to_s + merge_cached_response_key)
        else
          method + '_' + url.host + '_' + Digest::SHA1.hexdigest(scope.to_s + url.to_s)
        end
  body_msg = ''

  if Billy.config.cache_request_body_methods.include?(method) && !ignore_params && !merge_cached_response_key
    body_formatted = JSONUtils.json?(body.to_s) ? JSONUtils.sort_json(body.to_s) : body.to_s
    body_msg = " with body '#{body_formatted}'"
    key += '_' + Digest::SHA1.hexdigest(body_formatted)
  end

  Billy.log(:info, "puffing-billy: CACHE KEY for '#{orig_url}#{body_msg}' is '#{key}'") if log_key
  key
end

#persisted?(key) ⇒ Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/billy/cache.rb', line 23

def persisted?(key)
  Billy.config.persist_cache && File.exist?(cache_file(key))
end

#resetObject



67
68
69
# File 'lib/billy/cache.rb', line 67

def reset
  @cache = {}
end

#scope_to(new_scope = nil) ⇒ Object



130
131
132
# File 'lib/billy/cache.rb', line 130

def scope_to(new_scope = nil)
  self.scope = new_scope
end

#store(key, _scope, method, url, request_headers, body, response_headers, status, content) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/billy/cache.rb', line 39

def store(key, _scope, method, url, request_headers, body, response_headers, status, content)
  cached = {
    scope: _scope,
    url: format_url(url),
    body: body,
    status: status,
    method: method,
    headers: response_headers,
    content: content
  }

  cached.merge!(request_headers: request_headers) if Billy.config.cache_request_headers

  @cache[key] = cached

  if Billy.config.persist_cache
    Dir.mkdir(Billy.config.cache_path) unless File.exist?(Billy.config.cache_path)

    begin
      File.open(cache_file(key), 'w') do |f|
        f.write(cached.to_yaml(Encoding: :Utf8))
      end
    rescue StandardError => e
      Billy.log :error, "Error storing cache file: #{e.message}"
    end
  end
end

#use_default_scopeObject



143
144
145
# File 'lib/billy/cache.rb', line 143

def use_default_scope
  scope_to nil
end

#with_scope(use_scope = nil, &block) ⇒ Object



134
135
136
137
138
139
140
141
# File 'lib/billy/cache.rb', line 134

def with_scope(use_scope = nil, &block)
  fail ArgumentError, 'Expected a block but none was received.' if block.nil?
  original_scope = scope
  scope_to use_scope
  block.call
ensure
  scope_to original_scope
end