Class: Fizzy::Cache

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

Overview

ETag-based HTTP cache for GET requests (file-based, opt-in).

Stores responses keyed by URL with ETag validation. On cache hit with matching ETag, returns 304 Not Modified without re-downloading the body.

Examples:

cache = Fizzy::Cache.new(dir: "/tmp/fizzy-cache")
# Used internally by Http when cache is configured

Instance Method Summary collapse

Constructor Details

#initialize(dir:, max_entries: 1000) ⇒ Cache

Returns a new instance of Cache.

Parameters:

  • dir (String)

    directory for cache files

  • max_entries (Integer) (defaults to: 1000)

    maximum cache entries before eviction



19
20
21
22
23
# File 'lib/fizzy/cache.rb', line 19

def initialize(dir:, max_entries: 1000)
  @dir = dir
  @max_entries = max_entries
  FileUtils.mkdir_p(@dir)
end

Instance Method Details

#clearObject

Clears the entire cache.



70
71
72
# File 'lib/fizzy/cache.rb', line 70

def clear
  Dir.glob(File.join(@dir, "*.json")).each { |f| File.delete(f) }
end

#conditional_headers(url) ⇒ Hash?

Returns cached response headers for conditional request.

Parameters:

  • url (String)

    the request URL

Returns:

  • (Hash, nil)

    headers with If-None-Match if cached



28
29
30
31
32
33
# File 'lib/fizzy/cache.rb', line 28

def conditional_headers(url)
  entry = read_entry(url)
  return nil unless entry

  { "If-None-Match" => entry["etag"] }
end

#get(url) ⇒ String?

Returns cached body if available.

Parameters:

  • url (String)

    the request URL

Returns:

  • (String, nil)

    the cached body



57
58
59
60
# File 'lib/fizzy/cache.rb', line 57

def get(url)
  entry = read_entry(url)
  entry&.dig("body")
end

#invalidate(url) ⇒ Object

Invalidates a cache entry.

Parameters:

  • url (String)

    the request URL



64
65
66
67
# File 'lib/fizzy/cache.rb', line 64

def invalidate(url)
  path = entry_path(url)
  File.delete(path) if File.exist?(path)
end

#store(url, etag:, body:) ⇒ Object

Stores a response in the cache.

Parameters:

  • url (String)

    the request URL

  • etag (String)

    the ETag header value

  • body (String)

    the response body



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/fizzy/cache.rb', line 39

def store(url, etag:, body:)
  return if etag.nil? || etag.empty?

  evict_if_full

  entry = {
    "etag" => etag,
    "body" => body,
    "cached_at" => Time.now.to_i
  }

  path = entry_path(url)
  File.write(path, JSON.generate(entry))
end