blob: 30c8e0890614b7d58f99b368e7a77eea806685d8 (
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
|
# frozen_string_literal: true
module Gitlab
class AvatarCache
class << self
# Increment this if a breaking change requires
# immediate cache expiry of all avatar caches.
#
# @return [Integer]
VERSION = 1
# @return [Symbol]
BASE_KEY = :avatar_cache
# @return [ActiveSupport::Duration]
DEFAULT_EXPIRY = 7.days
# Look up cached avatar data by email address.
# This accepts a block to provide the value to be
# cached in the event nothing is found.
#
# Multiple calls in the same request will be served from the
# request store.
#
# @param email [String]
# @param additional_keys [*Object] all must respond to `#to_s`
# @param expires_in [ActiveSupport::Duration, Integer]
# @yield [email, *additional_keys] yields the supplied params back to the block
# @return [String]
def by_email(email, *additional_keys, expires_in: DEFAULT_EXPIRY)
key = email_key(email)
subkey = additional_keys.join(":")
Gitlab::SafeRequestStore.fetch([key, subkey]) do
with do |redis|
# Look for existing cache value
cached = redis.hget(key, subkey)
# Return the cached entry if set
break cached unless cached.nil?
# Otherwise, call the block to get the value
to_cache = yield(email, *additional_keys).to_s
# Set it in the cache
redis.hset(key, subkey, to_cache)
# Update the expiry time
redis.expire(key, expires_in)
# Return this new value
break to_cache
end
end
end
# Remove one or more emails from the cache
#
# @param emails [String] one or more emails to delete
# @return [Integer] the number of keys deleted
def delete_by_email(*emails)
return 0 if emails.empty?
with do |redis|
keys = emails.map { |email| email_key(email) }
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
redis.unlink(*keys)
end
end
end
private
# @param email [String]
# @return [String]
def email_key(email)
"#{BASE_KEY}:v#{VERSION}:#{email}"
end
def with(&blk)
Gitlab::Redis::Cache.with(&blk) # rubocop:disable CodeReuse/ActiveRecord
end
end
end
end
|