Module: ResponseCacheConcern
- Extended by:
- ActiveSupport::Concern
- Included in:
- Admin::AddOnsController, Api::Aoa::V1::BaseController, Api::Dashboard::BaseController, Api::Dashboard::ReservationsController, Api::Dashboard::V2::ReservationsController, Api::Partner::V1::BaseController, Api::Partner::V1::VouchersController, Api::V5::BaseController, Api::V5::Concerns::HhData::Restaurant, Api::V6::BaseController, Api::Vendor::V1::BaseController, Api::Vendor::V1::Dianping::BaseController, Api::Vendor::V1::Getyourguide::BaseController, Api::Vendor::V1::GoogleReserve::BaseController, Api::Vendor::V1::Klook::BaseController, Dashboard::V2::ReservationsController, HhMenu::ComparingPackageListsController, HhMenu::RestaurantsController, V2Users::BaseController
- Defined in:
- app/controllers/concerns/response_cache_concern.rb
Overview
typed: ignore frozen_string_literal: true
Instance Method Summary collapse
-
#my_response_cache(ck, format, options = {}, &block) ⇒ Object
this method is inspired by github.com/Shopify/response_bank gem but with more functionality, we can cache the response in redis and also in CDN (e.g. CloudFlare).
Instance Method Details
#my_response_cache(ck, format, options = {}, &block) ⇒ Object
this method is inspired by github.com/Shopify/response_bank gem but with more functionality, we can cache the response in redis and also in CDN (e.g. CloudFlare)
if caching is enabled and :public argument is not set, then the cache will be private and stored in redis but if :public is set to true, then the cache will be public and stored in CDN (e.g. CloudFlare) or browser
# How to use:
## Example 1: cache the response in redis with JSON format
cache_key = ['menus', action_name, current_user.id, params[:locale]
my_response_cache(cache_key, :json) do
{ success: true, message: '', data: restaurant.restaurant_packages }
end
## Example 2: cache the response in redis with HTML format
cache_key = ['menus', action_name, current_user.id, params[:locale]
my_response_cache(cache_key, :html) do
render_to_string
end
## Example 3: cache the response in CDN with JSON format
cache_key = ['menus', action_name, params[:locale]
my_response_cache(cache_key, :json, public: true) do
{ success: true, message: '', data: restaurant.restaurant_packages }
end
## Example 4: cache the response in CDN with HTML format
cache_key = ['menus', action_name, params[:locale]
my_response_cache(cache_key, :html, public: true) do
render_to_string
end
How to clear cache (example):
key = '*api_v5_cache:*'
$redis_lru.with do |conn|
# find any key that match "store_page_list"
conn.keys(key).each do |k|
if k.include? "store_page_list"
conn.del(k)
puts "Deleted key: #{k}"
end
end
end
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'app/controllers/concerns/response_cache_concern.rb', line 64 def my_response_cache(ck, format, = {}, &block) default_option = !(params[:__cache] == 'false') is_cache_enabled = .fetch(:enabled, default_option) expires_in = .fetch(:expires_in, 1.day) cache_by_public = .fetch(:public, false) public_expires_in = .fetch(:public_expires_in, DEFAULT_HTTP_PUBLIC_CACHE_EXPIRATION) force_write = .fetch(:force_write, false) debug_mode = true debug_params = .fetch(:debug_params) do debug_mode = false {} end class_name = self.class.to_s cache_key = ck.is_a?(Array) ? "response_cache:#{ck.join(':')}" : "response_cache:#{ck}" if is_cache_enabled && !force_write && !stale?(etag: cache_key, template: false) Rails.logger.debug("[cacheable][public: #{cache_by_public}] render hit cached CLIENT #{cache_key}") return head(:not_modified) end body = if is_cache_enabled # in the Cloudflare cache rule, we only cache the response if there is `locale` in the query string and method should GET if request.method == 'GET' && ENV['CLOUDFLARE_CACHE'].to_s == 'true' && cache_by_public && request.query_parameters['locale'].present? Rails.logger.debug("[cacheable] cache by public #{cache_key}") headers['Cache-Control'] = "max-age=#{public_expires_in.to_i}, public" # We can't depend on Cloudflare cache, because we can't clear the cache in Cloudflare perfectly # Whenever there is a new data in our side, hh-server touch the cache key correctly in Redis, # but not in Cloudflare, so we need to wait until the cache in Cloudflare is expired # That's why we use 5 minutes cache in Cloudflare, so the cache in Cloudflare will be expired in 5 minutes # FYI we use Cloudflare cache to reduce the server load only # The current implementation is not perfect, because we can't clear the cache in Cloudflare # We use Cloudflare premium plan, to Enterprise plan, to have the ability to clear the cache # using custom keys, such as wildcard, etc. cache_in_redis(cache_key, expires_in, format, force_write, debug_mode, debug_params, &block) else cache_in_redis(cache_key, expires_in, format, force_write, debug_mode, debug_params, &block) end else Rails.logger.debug("[cacheable] skip cache #{class_name}:#{action_name} #{ck.inspect}") my_render_to_string(format, &block) end content_type = format == :json ? Mime[:json].to_s : Mime[:html].to_s render body: body, content_type: content_type end |