diff options
Diffstat (limited to 'lib/gitlab/pages/cache_control.rb')
-rw-r--r-- | lib/gitlab/pages/cache_control.rb | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/lib/gitlab/pages/cache_control.rb b/lib/gitlab/pages/cache_control.rb index 187d5f907e4..be39e52b342 100644 --- a/lib/gitlab/pages/cache_control.rb +++ b/lib/gitlab/pages/cache_control.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'set' + module Gitlab module Pages class CacheControl @@ -9,7 +11,9 @@ module Gitlab # To avoid delivering expired deployment URL in the cached payload, # use a longer expiration time in the deployment URL DEPLOYMENT_EXPIRATION = (EXPIRE + 12.hours) - CACHE_KEY_FORMAT = 'pages_domain_for_%{type}_%{id}_%{settings}' + + SETTINGS_CACHE_KEY = 'pages_domain_for_%{type}_%{id}' + PAYLOAD_CACHE_KEY = '%{settings_cache_key}_%{settings_hash}' class << self def for_project(project_id) @@ -29,29 +33,63 @@ module Gitlab end def cache_key - strong_memoize(:cache_key) do - CACHE_KEY_FORMAT % { - type: @type, - id: @id, - settings: settings - } + strong_memoize(:payload_cache_key) do + cache_settings_hash! + + payload_cache_key_for(settings_hash) end end + # Invalidates the cache. + # + # Since rails nodes and sidekiq nodes have different application settings, + # and the invalidation happens in a sidekiq node, we have to use the + # cached settings hash to build the payload cache key to be invalidated. def clear_cache - Rails.cache.delete(cache_key) + keys = cached_settings_hashes + .map { |hash| payload_cache_key_for(hash) } + .push(settings_cache_key) + + Rails.cache.delete_multi(keys) end private - def settings - values = ::Gitlab.config.pages.dup + # Since rails nodes and sidekiq nodes have different application settings, + # we cache the application settings hash when creating the payload cache + # so we can use these values to invalidate the cache in a sidekiq node later. + def cache_settings_hash! + cached = cached_settings_hashes.to_set + Rails.cache.write(settings_cache_key, cached.add(settings_hash)) + end + + def cached_settings_hashes + Rails.cache.read(settings_cache_key) || [] + end + + def payload_cache_key_for(settings_hash) + PAYLOAD_CACHE_KEY % { + settings_cache_key: settings_cache_key, + settings_hash: settings_hash + } + end - values['app_settings'] = ::Gitlab::CurrentSettings.attributes.slice( - 'force_pages_access_control' - ) + def settings_cache_key + strong_memoize(:settings_cache_key) do + SETTINGS_CACHE_KEY % { type: @type, id: @id } + end + end - ::Digest::SHA256.hexdigest(values.inspect) + def settings_hash + strong_memoize(:settings_hash) do + values = ::Gitlab.config.pages.dup + + values['app_settings'] = ::Gitlab::CurrentSettings.attributes.slice( + 'force_pages_access_control' + ) + + ::Digest::SHA256.hexdigest(values.inspect) + end end end end |