blob: a24d958b7e56f3073fb9faa1503f7b46f846d927 (
plain)
1
2
3
4
5
6
7
8
9
10
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
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
|
# frozen_string_literal: true
require 'set'
module Gitlab
module Pages
class CacheControl
include Gitlab::Utils::StrongMemoize
EXPIRE = 12.hours
# To avoid delivering expired deployment URL in the cached payload,
# use a longer expiration time in the deployment URL
DEPLOYMENT_EXPIRATION = (EXPIRE + 12.hours)
SETTINGS_CACHE_KEY = 'pages_domain_for_%{type}_%{id}'
PAYLOAD_CACHE_KEY = '%{settings_cache_key}_%{settings_hash}'
class << self
def for_domain(domain_id)
new(type: :domain, id: domain_id)
end
def for_namespace(namespace_id)
new(type: :namespace, id: namespace_id)
end
end
def initialize(type:, id:)
raise(ArgumentError, "type must be :namespace or :domain") unless %i[namespace domain].include?(type)
@type = type
@id = id
end
def cache_key
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
keys = cached_settings_hashes
.map { |hash| payload_cache_key_for(hash) }
.push(settings_cache_key)
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
Rails.cache.delete_multi(keys)
end
end
private
# 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
def settings_cache_key
strong_memoize(:settings_cache_key) do
SETTINGS_CACHE_KEY % { type: @type, id: @id }
end
end
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
end
|