Module: Plugins::FrontCache::FrontCacheHelper
- Included in:
- AdminController
- Defined in:
- app/apps/plugins/front_cache/front_cache_helper.rb
Constant Summary collapse
- FRONT_CACHE_EXPIRATION =
Upper bound on any stored page's life. Stores whose purge is rescued away (RedisCacheStore and MemCacheStore reject the matcher) would otherwise keep retired or never-revisited entries forever — and Redis's default maxmemory-policy is noeviction, so TTL-less bodies would grow until the shared store refuses writes. An expired entry is an ordinary miss: the page is re-rendered and re-cached.
1.week
Instance Method Summary collapse
-
#front_cache_before_load ⇒ Object
expire cache for a page after comment registered or updated.
-
#front_cache_clean ⇒ Object
invalidate all cached pages of the current site.
- #front_cache_front_after_load ⇒ Object
-
#front_cache_front_before_load ⇒ Object
cache all pages configured in this plugin's settings for public users.
-
#front_cache_on_active(_plugin) ⇒ Object
on install plugin.
-
#front_cache_on_inactive(_plugin) ⇒ Object
on uninstall plugin.
-
#front_cache_on_render(_args) ⇒ Object
cache actions (for logged users).
- #front_cache_plugin_options(arg) ⇒ Object
-
#front_cache_post_requests ⇒ Object
invalidate the page cache on any content-changing request.
Instance Method Details
#front_cache_before_load ⇒ Object
expire cache for a page after comment registered or updated
111 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 111 def front_cache_before_load; end |
#front_cache_clean ⇒ Object
invalidate all cached pages of the current site
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 132 def front_cache_clean # Security: never Rails.cache.clear — the store is shared, and clearing it on every POST also # destroyed unrelated entries such as the per-IP login brute-force counter (CaptchaHelper), # silently defeating it. Bumping the version compared on every page-cache read (ActiveSupport # `version:`) retires all of this site's pages on any store, with no store enumeration. # # The version lives in its own meta key, apart from the front_cache_elements settings hash: # save_settings rewrites that hash wholesale from an earlier read, so a version stored inside # it could be reverted by a settings save racing a concurrent bump — and a reverted version # resurrects a retired generation as servable. current_site.('front_cache_counter', front_cache_version + 1) end |
#front_cache_front_after_load ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 69 def front_cache_front_after_load cache_key = front_cache_plugin_cache_key return unless @_plugin_do_cache && flash.keys.blank? body = response .body.gsub(/csrf-token" content="(.*?)"/, 'csrf-token" content="{{form_authenticity_token}}"') .gsub( /name="authenticity_token" value="(.*?)"/, 'name="authenticity_token" value="{{form_authenticity_token}}"' ) args = { data: body } hooks_run('front_cache_writing_cache', args) front_cache_plugin_cache_create(cache_key, args[:data]) Rails.logger.info "Camaleon CMS - cache saved as: #{front_cache_plugin_get_path(cache_key)}" end |
#front_cache_front_before_load ⇒ Object
cache all pages configured in this plugin's settings for public users
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 11 def front_cache_front_before_load # invalidate the site's cached pages on the first request after a (re)start, unless # preserve_cache_on_restart is checked in the plugin settings if current_site.get_option('refresh_cache') front_cache_clean unless (current_site.('front_cache_elements') || {})[:preserve_cache_on_restart] current_site.set_option('refresh_cache', false) end # avoid cache if the current visitor is logged in, or we're in the development or test environment return if signin? || Rails.env.development? || Rails.env.test? || !request.get? cache_key = front_cache_plugin_cache_key # Fail closed on a missing settings meta: front_cache runs on every frontend request, so an # absent front_cache_elements (never seeded, or hand-deleted) must degrade to "cache nothing" # rather than raise NoMethodError and 500 the whole public site. @caches = current_site.('front_cache_elements') || {} # Single read: the old exist?-then-get pair issued two store reads, and an entry vanishing # between them (a concurrent admin purge, TTL expiry) left .gsub running on nil — a # visitor-facing 500. cached_body = flash.keys.blank? ? front_cache_get(cache_key) : nil if cached_body # recover cache item Rails.logger.info "Camaleon CMS - readed cache: #{front_cache_plugin_get_path(cache_key)}" response.headers['PLUGIN_FRONT_CACHE'] = 'TRUE' args = { data: cached_body.gsub('{{form_authenticity_token}}', form_authenticity_token) } hooks_run('front_cache_reading_cache', args) # rubocop:disable Rails/OutputSafety -- This replays a trusted cached page body that was already rendered by Rails. render html: args[:data].html_safe # rubocop:enable Rails/OutputSafety return end @_plugin_do_cache = false # cache paths and home page paths = @caches[:paths] || [] if paths.include?(request.original_url) || paths.include?(request.path_info) || front_cache_plugin_match_path_patterns?(request.original_url, request.path_info) || (params[:action] == 'index' && params[:controller] == 'camaleon_cms/frontend' && @caches[:home].present?) @_plugin_do_cache = true elsif params[:action] == 'post' && params[:controller] == 'camaleon_cms/frontend' && params[:draft_id].blank? # the_post is a single-record lookup (eager: false) -- no listing preloads for one post # Never cache non-public posts. A password-protected post is unlocked per session (visibility_post # audit M2), but the page cache is keyed on the URL alone, so caching an unlocked render would # serve the protected body to visitors who never entered the password. Private posts are already # excluded; password posts must be too. if (post = current_site.the_post(params[:slug])) && post.can_visit? && !%w[private password].include?(post.visibility) if (@caches[:skip_posts] || []).include?(post.id.to_s) @_plugin_do_cache = false elsif (@caches[:post_types] || []).include?(post.post_type_id.to_s) || (@caches[:posts] || []).include?(post.id.to_s) @_plugin_do_cache = true end end end response.headers['PLUGIN_FRONT_CACHE'] = 'TRUE' if @_plugin_do_cache end |
#front_cache_on_active(_plugin) ⇒ Object
on install plugin
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 86 def front_cache_on_active(_plugin) return if current_site.('front_cache_elements', nil).present? current_site.( 'front_cache_elements', { paths: [], posts: [], post_types: [current_site.post_types.where(slug: 'page').first.id], skip_posts: [], home: true, cache_login: true } ) end |
#front_cache_on_inactive(_plugin) ⇒ Object
on uninstall plugin
103 104 105 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 103 def front_cache_on_inactive(_plugin) # current_site.delete_meta("front_cache_elements") end |
#front_cache_on_render(_args) ⇒ Object
cache actions (for logged users)
108 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 108 def front_cache_on_render(_args); end |
#front_cache_plugin_options(arg) ⇒ Object
113 114 115 116 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 113 def (arg) arg[:links] << link_to(t('plugin.front_cache.settings'), admin_plugins_front_cache_settings_path) arg[:links] << link_to(t('plugin.front_cache.clean_cache'), admin_plugins_front_cache_clean_path) end |
#front_cache_post_requests ⇒ Object
invalidate the page cache on any content-changing request. PUT and DELETE count: a permanent post deletion rides DELETE (Rack::MethodOverride makes request.post? false for _method=delete forms), and without a bump the deleted page kept being served from cache.
121 122 123 124 125 126 127 128 129 |
# File 'app/apps/plugins/front_cache/front_cache_helper.rb', line 121 def front_cache_post_requests return unless request.post? || request.put? || request.patch? || request.delete? # A draft autosave (posts/drafts) writes a private draft_child buffer, never published # output, so it must not retire the public page cache — otherwise an open editor's # per-minute autosave keeps the whole site's cache from ever warming. return if params[:controller].to_s.end_with?('posts/drafts') front_cache_clean end |