Class: Lutaml::Store::HttpCache

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/store/http_cache.rb

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ HttpCache

Returns a new instance of HttpCache.



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/lutaml/store/http_cache.rb', line 8

def initialize(config)
  @config = config.is_a?(HttpCacheConfig) ? config : HttpCacheConfig.new(config)
  @config.validate!
  @adapter = create_adapter
  @stats = {
    cache_hits: 0,
    cache_misses: 0,
    conditional_requests: 0,
    not_modified_responses: 0,
    entries_stored: 0,
    entries_evicted: 0
  }
end

Instance Method Details

#all_entriesObject

Get all cache entries for inspection



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/lutaml/store/http_cache.rb', line 142

def all_entries
  entries = []
  @adapter.each_key do |key|
    data = @adapter.get(key)
    next unless data

    entry_data = data.is_a?(String) ? JSON.parse(data) : data
    entry = HttpCacheEntry.from_hash(entry_data)
    entries << entry
  rescue StandardError
    # Skip invalid entries
  end
  entries
end

#clearObject

Clear all cache entries



110
111
112
113
114
# File 'lib/lutaml/store/http_cache.rb', line 110

def clear
  @adapter.clear
rescue StandardError
  false
end

#delete(method, url, headers = {}) ⇒ Object

Delete cached entry



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/lutaml/store/http_cache.rb', line 93

def delete(method, url, headers = {})
  vary_headers = extract_request_vary_headers(headers)
  cache_key = HttpHeaderProcessor.generate_cache_key(
    method,
    url,
    vary_headers,
    @config.ignore_query_params
  )

  prefixed_key = @config.cache_key_for(cache_key)
  @adapter.delete(prefixed_key)
rescue StandardError
  # Log error but don't fail
  false
end

#fetch(method, url, headers = {}, &block) ⇒ Object

Main cache interface - fetch with block for cache miss

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/lutaml/store/http_cache.rb', line 23

def fetch(method, url, headers = {}, &block)
  raise ArgumentError, "Block required for cache miss handling" unless block_given?

  # Generate cache key considering vary headers
  vary_headers = extract_request_vary_headers(headers)
  cache_key = HttpHeaderProcessor.generate_cache_key(
    method,
    url,
    vary_headers,
    @config.ignore_query_params
  )

  prefixed_key = @config.cache_key_for(cache_key)
  entry = get_entry(prefixed_key)

  # Check if entry matches current request (Vary header consideration)
  if entry && cache_entry_matches?(entry, headers)
    if entry.fresh?
      @stats[:cache_hits] += 1
      return create_response_from_entry(entry)
    elsif entry.stale? && @config.enable_conditional_requests
      # Try conditional request
      @stats[:conditional_requests] += 1
      return handle_conditional_request(entry, headers, prefixed_key, &block)
    end
  end

  # Cache miss or unusable entry - make fresh request
  @stats[:cache_misses] += 1
  response = yield(headers)
  cache_response(prefixed_key, method, url, headers, response)
end

#get(method, url, headers = {}) ⇒ Object

Get cached entry without making requests



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/lutaml/store/http_cache.rb', line 57

def get(method, url, headers = {})
  vary_headers = extract_request_vary_headers(headers)
  cache_key = HttpHeaderProcessor.generate_cache_key(
    method,
    url,
    vary_headers,
    @config.ignore_query_params
  )

  prefixed_key = @config.cache_key_for(cache_key)
  entry = get_entry(prefixed_key)

  return nil unless entry
  return nil unless cache_entry_matches?(entry, headers)
  return nil unless entry.fresh?

  create_response_from_entry(entry)
end

#set(method, url, headers, response) ⇒ Object

Store response in cache



77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/lutaml/store/http_cache.rb', line 77

def set(method, url, headers, response)
  return response unless should_cache_response?(response)

  vary_headers = extract_request_vary_headers(headers)
  cache_key = HttpHeaderProcessor.generate_cache_key(
    method,
    url,
    vary_headers,
    @config.ignore_query_params
  )

  prefixed_key = @config.cache_key_for(cache_key)
  cache_response(prefixed_key, method, url, headers, response)
end

#statsObject

Get cache statistics



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/lutaml/store/http_cache.rb', line 117

def stats
  total_requests = @stats[:cache_hits] + @stats[:cache_misses]
  hit_ratio = total_requests.positive? ? (@stats[:cache_hits].to_f / total_requests * 100) : 0

  {
    adapter_type: @config.adapter_type,
    total_entries: @adapter.size,
    cache_hits: @stats[:cache_hits],
    cache_misses: @stats[:cache_misses],
    conditional_requests: @stats[:conditional_requests],
    not_modified_responses: @stats[:not_modified_responses],
    entries_stored: @stats[:entries_stored],
    entries_evicted: @stats[:entries_evicted],
    hit_ratio: hit_ratio,
    total_requests: total_requests,
    config: {
      default_ttl: @config.default_ttl,
      max_entries: @config.max_entries,
      respect_http_headers: @config.respect_http_headers,
      enable_conditional_requests: @config.enable_conditional_requests
    }
  }
end