Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-16 21:18:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-16 21:18:33 +0300
commitf64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch)
treea2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /lib/gitlab/avatar_cache.rb
parentbfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff)
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'lib/gitlab/avatar_cache.rb')
-rw-r--r--lib/gitlab/avatar_cache.rb86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/gitlab/avatar_cache.rb b/lib/gitlab/avatar_cache.rb
new file mode 100644
index 00000000000..30c8e089061
--- /dev/null
+++ b/lib/gitlab/avatar_cache.rb
@@ -0,0 +1,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