class HTTPDisk::Cache

Disk cache for cache_keys => response. Files are compressed.

Attributes

options[R]

Public Class Methods

new(options) click to toggle source
# File lib/httpdisk/cache.rb, line 9
def initialize(options)
  @options = options
end

Public Instance Methods

delete(cache_key) click to toggle source

Delete existing response, if any

# File lib/httpdisk/cache.rb, line 55
def delete(cache_key)
  path = diskpath(cache_key)
  FileUtils.rm(path) if File.exist?(path)
end
diskpath(cache_key) click to toggle source

Relative path for this cache_key based on the cache key

# File lib/httpdisk/cache.rb, line 61
def diskpath(cache_key)
  File.join(dir, cache_key.diskpath)
end
read(cache_key) click to toggle source

Get cached response. If there is a cached error it will be raised.

# File lib/httpdisk/cache.rb, line 22
def read(cache_key)
  payload_or_status = read0(cache_key)
  payload_or_status.is_a?(Symbol) ? nil : payload_or_status
end
status(cache_key) click to toggle source

Cache status for a cache_key, %i[error force hit miss stale]

# File lib/httpdisk/cache.rb, line 28
def status(cache_key)
  payload_or_status = read0(cache_key, peek: true)
  return payload_or_status if payload_or_status.is_a?(Symbol)

  payload_or_status.error? ? :error : :hit
end
write(cache_key, payload) click to toggle source

Write response to the disk cache

# File lib/httpdisk/cache.rb, line 36
def write(cache_key, payload)
  path = diskpath(cache_key)
  FileUtils.mkdir_p(File.dirname(path))

  # Atomically write gzipped payload. Put our underlying Tempfile into
  # binmode to avoid accidental newline conversion or string encoding. Not
  # required for *nix systems, but I've heard rumors it's helpful for
  # Windows.
  Tempfile.new(binmode: true).tap do |tmp|
    Zlib::GzipWriter.new(tmp).tap do |gzip|
      payload.write(gzip)
      gzip.close
    end
    tmp.close
    FileUtils.mv(tmp.path, path)
  end
end

Protected Instance Methods

expired?(path) click to toggle source

Is this path expired?

# File lib/httpdisk/cache.rb, line 88
def expired?(path)
  expires && File.stat(path).mtime < Time.now - expires
end
read0(cache_key, peek: false) click to toggle source

low level read, returns payload or status

# File lib/httpdisk/cache.rb, line 68
def read0(cache_key, peek: false)
  path = diskpath(cache_key)

  return :miss if !File.exist?(path)
  return :stale if expired?(path)
  return :force if force?

  begin
    payload = Zlib::GzipReader.open(path, encoding: 'ASCII-8BIT') do
      Payload.read(_1, peek: peek)
    end
  rescue StandardError => e
    raise "#{path}: #{e}"
  end
  return :force if force_errors? && payload.error?

  payload
end