class Routemaster::Middleware::ResponseCaching

Constants

BODY_FIELD_TEMPLATE
HEADERS_FIELD_TEMPLATE
RESPONSE_CACHING_OPT_HEADER
VERSION_REGEX

Public Class Methods

new(app, options = {}) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 13
def initialize(app, options = {})
  @app = app
  @cache = options.fetch(:cache) { Config.cache_redis }
  @expiry = Config.cache_expiry
  @listener = options[:listener]
end

Public Instance Methods

call(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 20
def call(env)
  @cache.del(cache_key(env)) if %i(patch delete).include?(env.method)
  return @app.call(env) if env.method != :get
  fetch_from_cache(env) || fetch_from_service(env, event_index(env))
end

Private Instance Methods

body_cache_field(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 69
def body_cache_field(env)
  BODY_FIELD_TEMPLATE
    .gsub('{version}', version(env).to_s)
    .gsub('{locale}', locale(env).to_s)
end
cache_enabled?(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 97
def cache_enabled?(env)
  env.request_headers[RESPONSE_CACHING_OPT_HEADER].to_s == 'true'
end
cache_key(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 81
def cache_key(env)
  CacheKey.url_key(url(env))
end
currently_cached_content(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 105
def currently_cached_content(env)
  @cache.hmget(cache_key(env),
               body_cache_field(env),
               headers_cache_field(env),
               :most_recent_index,
               :current_index)
end
event_index(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 101
def event_index(env)
  Routemaster::EventIndex.new(url(env)).current
end
fetch_from_cache(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 51
def fetch_from_cache(env)
  return nil unless cache_enabled?(env)
  body, headers, most_recent_index, current_index = currently_cached_content(env)

  unless most_recent_index.to_i == current_index.to_i && body && headers
    Config.logger.debug("DRAIN: Cache miss #{url(env)} - index_recent: #{most_recent_index.to_i}") if Config.logger.debug?
    return nil
  end

  Config.logger.debug("DRAIN: Cache hit #{url(env)} - index_recent: #{most_recent_index.to_i}") if Config.logger.debug?
  @listener._publish(:cache_hit, url(env)) if @listener

  Faraday::Response.new(status: 200,
                        body: body,
                        response_headers: Marshal.load(headers),
                        request: {})
end
fetch_from_service(env, event_index) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 28
def fetch_from_service(env, event_index)
  @app.call(env).on_complete do |response_env|
    response = response_env.response

    if response.success? && cache_enabled?(env)
      namespaced_key = "#{@cache.namespace}:#{cache_key(env)}"
      @cache.redis.node_for(namespaced_key).multi do |node|
        if Config.logger.debug?
          Config.logger.debug("DRAIN: Saving #{url(env)} with a event index of #{event_index}")
        end

        node.hmset(namespaced_key,
                   body_cache_field(env), response.body,
                   headers_cache_field(env), Marshal.dump(response.headers),
                   :most_recent_index, event_index)
        node.expire(namespaced_key, @expiry)
      end

      @listener._publish(:cache_miss, url(env)) if @listener
    end
  end
end
headers_cache_field(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 75
def headers_cache_field(env)
  HEADERS_FIELD_TEMPLATE
    .gsub('{version}', version(env).to_s)
    .gsub('{locale}', locale(env).to_s)
end
locale(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 93
def locale(env)
  env.request_headers['Accept-Language']
end
url(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 85
def url(env)
  env.url.to_s
end
version(env) click to toggle source
# File lib/routemaster/middleware/response_caching.rb, line 89
def version(env)
  (env.request_headers['Accept'] || '')[VERSION_REGEX, 1]
end