Class: Factorix::HTTP::CacheDecorator

Inherits:
Object
  • Object
show all
Defined in:
lib/factorix/http/cache_decorator.rb

Overview

Adds caching for GET requests

Stores successful GET responses in FileSystem cache. Only caches non-streaming requests (no block given).

Instance Method Summary collapse

Instance Method Details

#get(uri, headers: {}) {|Net::HTTPResponse| ... } ⇒ Response, Object

Execute a GET request with caching

Parameters:

  • uri (URI::HTTPS)

    target URI

  • headers (Hash<String, String>) (defaults to: {})

    request headers

Yields:

  • (Net::HTTPResponse)

    for streaming responses

Returns:

  • (Response, Object)

    response object or parsed data



49
50
51
52
53
54
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
81
82
83
84
85
86
# File 'lib/factorix/http/cache_decorator.rb', line 49

def get(uri, headers: {}, &block)
  # Don't cache streaming requests
  return client.get(uri, headers:, &block) if block

  cache_key = uri.to_s

  cached_body = cache.read(cache_key)
  if cached_body
    logger.debug("Cache hit", uri: uri.to_s)
    publish("cache.hit", url: uri.to_s)
    return CachedResponse.new(cached_body, uri:)
  end

  logger.debug("Cache miss", uri: uri.to_s)
  publish("cache.miss", url: uri.to_s)

  # Locking prevents concurrent downloads of the same resource
  cache.with_lock(cache_key) do
    # Double-check: another thread might have filled the cache
    cached_body = cache.read(cache_key)
    if cached_body
      publish("cache.hit", url: uri.to_s)
      return CachedResponse.new(cached_body, uri:)
    end

    response = client.get(uri, headers:)

    if response.success?
      with_temporary_file do |temp|
        temp.write(response.body)
        temp.close
        cache.store(cache_key, Pathname(temp.path))
      end
    end

    response
  end
end

#head(uri, headers: {}) ⇒ Response

Execute a HEAD request (never cached)

Parameters:

  • uri (URI::HTTPS)

    target URI

  • headers (Hash<String, String>) (defaults to: {})

    request headers

Returns:



102
# File 'lib/factorix/http/cache_decorator.rb', line 102

def head(uri, headers: {}) = client.head(uri, headers:)

#post(uri, body:, headers: {}, content_type: nil) ⇒ Response

Execute a POST request (never cached)

Parameters:

  • uri (URI::HTTPS)

    target URI

  • body (String, IO)

    request body

  • headers (Hash<String, String>) (defaults to: {})

    request headers

  • content_type (String, nil) (defaults to: nil)

    Content-Type header

Returns:



95
# File 'lib/factorix/http/cache_decorator.rb', line 95

def post(uri, body:, headers: {}, content_type: nil) = client.post(uri, body:, headers:, content_type:)

#request(method, uri, headers: {}, body: nil) {|Net::HTTPResponse| ... } ⇒ Response, Object

Execute an HTTP request (only caches GET without block)

Parameters:

  • method (Symbol)

    HTTP method

  • uri (URI::HTTPS)

    target URI

  • headers (Hash<String, String>) (defaults to: {})

    request headers

  • body (String, IO, nil) (defaults to: nil)

    request body

Yields:

  • (Net::HTTPResponse)

    for streaming responses

Returns:

  • (Response, Object)

    response object or parsed data



35
36
37
38
39
40
41
# File 'lib/factorix/http/cache_decorator.rb', line 35

def request(method, uri, headers: {}, body: nil, &block)
  if method == :get && !block
    get(uri, headers:)
  else
    client.request(method, uri, headers:, body:, &block)
  end
end