87 lines
2.4 KiB
Ruby
87 lines
2.4 KiB
Ruby
|
# 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
|