Commit 3edf027a authored by Robert May's avatar Robert May

Add race_condition_ttl support

Prevents multiple writes under heavy load.
parent 09d74fc0
......@@ -11,6 +11,11 @@ module API
# @return [ActiveSupport::Duration]
DEFAULT_EXPIRY = 1.day
# @return [Hash]
DEFAULT_CACHE_OPTIONS = {
race_condition_ttl: 5.seconds
}.freeze
# @return [ActiveSupport::Cache::Store]
def cache
Rails.cache
......@@ -75,7 +80,7 @@ module API
# @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
# @return [Gitlab::Json::PrecompiledJson]
def cache_action(key, **cache_opts)
json = cache.fetch(key, **cache_opts) do
json = cache.fetch(key, **apply_default_cache_options(cache_opts)) do
Gitlab::Json.dump(yield.as_json)
end
......@@ -106,6 +111,10 @@ module API
private
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
......
......@@ -170,8 +170,10 @@ RSpec.describe API::Helpers::Caching, :use_clean_rails_redis_caching do
end
it "only calls the expensive action once" do
expected_kwargs = described_class::DEFAULT_CACHE_OPTIONS.merge(kwargs)
expect(expensive_thing).to receive(:do_very_expensive_action).once
expect(instance.cache).to receive(:fetch).with(cache_key, **kwargs).exactly(5).times.and_call_original
expect(instance.cache).to receive(:fetch).with(cache_key, **expected_kwargs).exactly(5).times.and_call_original
5.times { perform }
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment