diff options
Diffstat (limited to 'lib/api/helpers/caching.rb')
-rw-r--r-- | lib/api/helpers/caching.rb | 82 |
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 |