Class: Gitlab::RepositoryHashCache
- Inherits:
-
Object
- Object
- Gitlab::RepositoryHashCache
- Defined in:
- lib/gitlab/repository_hash_cache.rb
Constant Summary collapse
- RepositoryHashCacheError =
Class.new(StandardError)
- InvalidKeysProvidedError =
Class.new(RepositoryHashCacheError)
- InvalidHashProvidedError =
Class.new(RepositoryHashCacheError)
Instance Attribute Summary collapse
-
#expires_in ⇒ Object
readonly
Returns the value of attribute expires_in.
-
#namespace ⇒ Object
readonly
Returns the value of attribute namespace.
-
#repository ⇒ Object
readonly
Returns the value of attribute repository.
Instance Method Summary collapse
- #cache_key(type) ⇒ String
-
#delete(*keys) ⇒ Integer
The number of keys successfully deleted.
-
#fetch_and_add_missing(key, h_keys) {|missing_keys, new_values| ... } ⇒ Hash
A variation on the ‘fetch` pattern of other cache stores.
-
#initialize(repository, extra_namespace: nil, expires_in: 1.day) ⇒ RepositoryHashCache
constructor
A new instance of RepositoryHashCache.
-
#key?(key, h_key) ⇒ True, False
Check if the provided hash key exists in the hash.
-
#read_members(key, hash_keys = []) ⇒ Hash
Read the values of a set of keys from the hash store, and return them as a hash of those keys and their values.
-
#write(key, hash) ⇒ Boolean
Write a hash to the store.
Constructor Details
#initialize(repository, extra_namespace: nil, expires_in: 1.day) ⇒ RepositoryHashCache
Returns a new instance of RepositoryHashCache.
20 21 22 23 24 25 26 |
# File 'lib/gitlab/repository_hash_cache.rb', line 20 def initialize(repository, extra_namespace: nil, expires_in: 1.day) @repository = repository @namespace = "#{repository.full_path}" @namespace += ":#{repository.project.id}" if repository.project @namespace = "#{@namespace}:#{extra_namespace}" if extra_namespace @expires_in = expires_in end |
Instance Attribute Details
#expires_in ⇒ Object (readonly)
Returns the value of attribute expires_in.
11 12 13 |
# File 'lib/gitlab/repository_hash_cache.rb', line 11 def expires_in @expires_in end |
#namespace ⇒ Object (readonly)
Returns the value of attribute namespace.
11 12 13 |
# File 'lib/gitlab/repository_hash_cache.rb', line 11 def namespace @namespace end |
#repository ⇒ Object (readonly)
Returns the value of attribute repository.
11 12 13 |
# File 'lib/gitlab/repository_hash_cache.rb', line 11 def repository @repository end |
Instance Method Details
#cache_key(type) ⇒ String
30 31 32 |
# File 'lib/gitlab/repository_hash_cache.rb', line 30 def cache_key(type) "#{type}:#{namespace}:hash" end |
#delete(*keys) ⇒ Integer
Returns the number of keys successfully deleted.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/gitlab/repository_hash_cache.rb', line 36 def delete(*keys) return 0 if keys.empty? with do |redis| keys = keys.map { |key| cache_key(key) } Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do if Gitlab::Redis::ClusterUtil.cluster?(redis) Gitlab::Redis::ClusterUtil.batch_unlink(keys, redis) else redis.unlink(*keys) end end end end |
#fetch_and_add_missing(key, h_keys) {|missing_keys, new_values| ... } ⇒ Hash
A variation on the ‘fetch` pattern of other cache stores. This method allows you to attempt to fetch a group of keys from the hash store, and for any keys that are missing values a block is then called to provide those values, which are then written back into Redis. Both sets of data are then combined and returned as one hash.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/gitlab/repository_hash_cache.rb', line 115 def fetch_and_add_missing(key, h_keys, &block) # Check the cache for all supplied keys cache_values = read_members(key, h_keys) # Find the results which returned nil (meaning they're not in the cache) missing = cache_values.select { |_, v| v.nil? }.keys if missing.any? new_values = {} # Run the block, which updates the new_values hash yield(missing, new_values) # Ensure all values are converted to strings, to ensure merging hashes # below returns standardised data. new_values = standardize_hash(new_values) # Write the new values to the hset write(key, new_values) # Merge the two sets of values to return a complete hash cache_values.merge!(new_values) end record_metrics(key, cache_values, missing) cache_values end |
#key?(key, h_key) ⇒ True, False
Check if the provided hash key exists in the hash.
57 58 59 |
# File 'lib/gitlab/repository_hash_cache.rb', line 57 def key?(key, h_key) with { |redis| redis.hexists(cache_key(key), h_key) } end |
#read_members(key, hash_keys = []) ⇒ Hash
Read the values of a set of keys from the hash store, and return them as a hash of those keys and their values.
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/gitlab/repository_hash_cache.rb', line 67 def read_members(key, hash_keys = []) raise InvalidKeysProvidedError unless hash_keys.is_a?(Array) && hash_keys.any? with do |redis| # Fetch an array of values for the supplied keys values = redis.hmget(cache_key(key), hash_keys) # Turn it back into a hash hash_keys.zip(values).to_h end end |
#write(key, hash) ⇒ Boolean
Write a hash to the store. All keys and values will be strings when stored.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/gitlab/repository_hash_cache.rb', line 84 def write(key, hash) raise InvalidHashProvidedError unless hash.is_a?(Hash) && hash.any? full_key = cache_key(key) with do |redis| results = redis.pipelined do |pipeline| # Set each hash key to the provided value hash.each do |h_key, h_value| pipeline.hset(full_key, h_key, h_value) end # Update the expiry time for this hset pipeline.expire(full_key, expires_in) end results.all? end end |