diff options
author | Michael Kozono <mkozono@gmail.com> | 2018-09-25 20:12:51 +0300 |
---|---|---|
committer | Michael Kozono <mkozono@gmail.com> | 2018-09-28 04:22:37 +0300 |
commit | 3640292bf2ef822c8e2394fa2397b1b7d04e9891 (patch) | |
tree | e6083dca766e7acfb94b613329a43c98a8aa526b /lib | |
parent | d9c4ebc5a0b2e911f17865e482de1dfcc2189ac3 (diff) |
Cache `Repository#exists?` false in RequestStore
* Only truthy values are cached in Redis.
* All values are cached in RequestStore and in an instance variable.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/repository_cache.rb | 16 | ||||
-rw-r--r-- | lib/gitlab/repository_cache_adapter.rb | 36 |
2 files changed, 52 insertions, 0 deletions
diff --git a/lib/gitlab/repository_cache.rb b/lib/gitlab/repository_cache.rb index b1bf3ca4143..a03ce07b6a1 100644 --- a/lib/gitlab/repository_cache.rb +++ b/lib/gitlab/repository_cache.rb @@ -29,5 +29,21 @@ module Gitlab def read(key) backend.read(cache_key(key)) end + + def write(key, value) + backend.write(cache_key(key), value) + end + + def fetch_without_caching_false(key, &block) + value = read(key) + return value if value + + value = yield + + # Don't cache false values + write(key, value) if value + + value + end end end diff --git a/lib/gitlab/repository_cache_adapter.rb b/lib/gitlab/repository_cache_adapter.rb index f7318f81613..bd0e51cbfe5 100644 --- a/lib/gitlab/repository_cache_adapter.rb +++ b/lib/gitlab/repository_cache_adapter.rb @@ -15,6 +15,20 @@ module Gitlab wrap_method(name, :cache_method_output, fallback: fallback) end + # Caches truthy values from the method. All values are strongly memoized, + # and cached in RequestStore. + # + # Currently only used to cache `exists?` since stale false values are + # particularly troublesome. This can occur, for example, when an NFS mount + # is temporarily down. + # + # This only works for methods that do not take any arguments. + # + # name - The name of the method to be cached. + def cache_method_asymmetrically(name) + wrap_method(name, :cache_method_output_asymmetrically) + end + # Strongly memoizes the method. # # This only works for methods that do not take any arguments. @@ -42,6 +56,12 @@ module Gitlab end end + # RequestStore-backed RepositoryCache to be used. Should be overridden by + # the including class + def request_store_cache + raise NotImplementedError + end + # RepositoryCache to be used. Should be overridden by the including class def cache raise NotImplementedError @@ -63,6 +83,22 @@ module Gitlab end end + # Caches truthy values from the supplied block. All values are strongly + # memoized, and cached in RequestStore. + # + # Currently only used to cache `exists?` since stale false values are + # particularly troublesome. This can occur, for example, when an NFS mount + # is temporarily down. + # + # name - The name of the method to be cached. + def cache_method_output_asymmetrically(name, &block) + memoize_method_output(name) do + request_store_cache.fetch(name) do + cache.fetch_without_caching_false(name, &block) + end + end + end + # Strongly memoizes the supplied block. # # name - The name of the method to be memoized. |