summaryrefslogtreecommitdiff
path: root/lib/api/helpers/caching.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/api/helpers/caching.rb')
-rw-r--r--lib/api/helpers/caching.rb82
1 files changed, 2 insertions, 80 deletions
diff --git a/lib/api/helpers/caching.rb b/lib/api/helpers/caching.rb
index f24ac7302c1..dfb9708dd3c 100644
--- a/lib/api/helpers/caching.rb
+++ b/lib/api/helpers/caching.rb
@@ -8,19 +8,12 @@
module API
module Helpers
module Caching
- # @return [ActiveSupport::Duration]
- DEFAULT_EXPIRY = 1.day
-
+ include Gitlab::Cache::Helpers
# @return [Hash]
DEFAULT_CACHE_OPTIONS = {
race_condition_ttl: 5.seconds
}.freeze
- # @return [ActiveSupport::Cache::Store]
- def cache
- Rails.cache
- end
-
# This is functionally equivalent to the standard `#present` used in
# Grape endpoints, but the JSON for the object, or for each object of
# a collection, will be cached.
@@ -45,7 +38,7 @@ module API
# @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
# @param presenter_args [Hash] keyword arguments to be passed to the entity
# @return [Gitlab::Json::PrecompiledJson]
- def present_cached(obj_or_collection, with:, cache_context: -> (_) { current_user&.cache_key }, expires_in: DEFAULT_EXPIRY, **presenter_args)
+ def present_cached(obj_or_collection, with:, cache_context: -> (_) { current_user&.cache_key }, expires_in: Gitlab::Cache::Helpers::DEFAULT_EXPIRY, **presenter_args)
json =
if obj_or_collection.is_a?(Enumerable)
cached_collection(
@@ -120,77 +113,6 @@ module API
def apply_default_cache_options(opts = {})
DEFAULT_CACHE_OPTIONS.merge(opts)
end
-
- # Optionally uses a `Proc` to add context to a cache key
- #
- # @param object [Object] must respond to #cache_key
- # @param context [Proc] a proc that will be called with the object as an argument, and which should return a
- # string or array of strings to be combined into the cache key
- # @return [String]
- def contextual_cache_key(object, context)
- return object.cache_key if context.nil?
-
- [object.cache_key, context.call(object)].flatten.join(":")
- end
-
- # Used for fetching or rendering a single object
- #
- # @param object [Object] the object to render
- # @param presenter [Grape::Entity]
- # @param presenter_args [Hash] keyword arguments to be passed to the entity
- # @param context [Proc]
- # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
- # @return [String]
- def cached_object(object, presenter:, presenter_args:, context:, expires_in:)
- cache.fetch(contextual_cache_key(object, context), expires_in: expires_in) do
- Gitlab::Json.dump(presenter.represent(object, **presenter_args).as_json)
- end
- end
-
- # Used for fetching or rendering multiple objects
- #
- # @param objects [Enumerable<Object>] the objects to render
- # @param presenter [Grape::Entity]
- # @param presenter_args [Hash] keyword arguments to be passed to the entity
- # @param context [Proc]
- # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
- # @return [Array<String>]
- def cached_collection(collection, presenter:, presenter_args:, context:, expires_in:)
- json = fetch_multi(collection, context: context, expires_in: expires_in) do |obj|
- Gitlab::Json.dump(presenter.represent(obj, **presenter_args).as_json)
- end
-
- json.values
- end
-
- # An adapted version of ActiveSupport::Cache::Store#fetch_multi.
- #
- # The original method only provides the missing key to the block,
- # not the missing object, so we have to create a map of cache keys
- # to the objects to allow us to pass the object to the missing value
- # block.
- #
- # The result is that this is functionally identical to `#fetch`.
- def fetch_multi(*objs, context:, **kwargs)
- objs.flatten!
- map = multi_key_map(objs, context: context)
-
- # TODO: `contextual_cache_key` should be constructed based on the guideline https://docs.gitlab.com/ee/development/redis.html#multi-key-commands.
- Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
- cache.fetch_multi(*map.keys, **kwargs) do |key|
- yield map[key]
- end
- end
- end
-
- # @param objects [Enumerable<Object>] objects which _must_ respond to `#cache_key`
- # @param context [Proc] a proc that can be called to help generate each cache key
- # @return [Hash]
- def multi_key_map(objects, context:)
- objects.index_by do |object|
- contextual_cache_key(object, context)
- end
- end
end
end
end