Module: Gitlab::Cache::Import::Caching
- Defined in:
- lib/gitlab/cache/import/caching.rb
Constant Summary collapse
- TIMEOUT =
The default timeout of the cache keys.
24.hours.to_i
- LONGER_TIMEOUT =
72.hours.to_i
- SHORTER_TIMEOUT =
15.minutes.to_i
- WRITE_IF_GREATER_SCRIPT =
<<-EOF.strip_heredoc.freeze local key, value, ttl = KEYS[1], tonumber(ARGV[1]), ARGV[2] local existing = tonumber(redis.call("get", key)) if existing == nil or value > existing then redis.call("set", key, value) redis.call("expire", key, ttl) return true else return false end EOF
Class Method Summary collapse
- .cache_key_for(raw_key) ⇒ Object
-
.del(raw_key) ⇒ Object
Deletes a key.
-
.expire(raw_key, timeout) ⇒ Object
Sets the expiration time of a key.
-
.hash_add(raw_key, field, value, timeout: TIMEOUT) ⇒ Object
Adds a value to a hash.
-
.hash_increment(raw_key, field, value, timeout: TIMEOUT) ⇒ Object
Increments value of a field in a hash.
-
.increment(raw_key, timeout: TIMEOUT) ⇒ Object
Increment the integer value of a key by one.
-
.increment_by(raw_key, value, timeout: TIMEOUT) ⇒ Object
Increment the integer value of a key by the given value.
-
.limited_values_from_set(raw_key, limit: 1) ⇒ Object
Returns a limited number of random values from the set.
-
.list_add(raw_key, value, timeout: TIMEOUT, limit: nil) ⇒ Object
Adds a value to a list.
-
.read(raw_key, timeout: TIMEOUT) ⇒ Object
Reads a cache key.
-
.read_integer(raw_key, timeout: TIMEOUT) ⇒ Object
Reads an integer from the cache, or returns nil if no value was found.
-
.set_add(raw_key, value, timeout: TIMEOUT) ⇒ Object
Adds a value to a set.
-
.set_count(raw_key) ⇒ Object
Returns the number of values in the set.
-
.set_includes?(raw_key, value) ⇒ Boolean
Returns true if the given value is present in the set.
-
.set_remove(raw_key, values = []) ⇒ Object
Removes the given values from the set.
- .validate_redis_value!(value) ⇒ Object
-
.value_from_hash(raw_key, field, timeout: TIMEOUT) ⇒ Object
Returns a single value of the given hash.
-
.values_from_hash(raw_key) ⇒ Object
Returns the values of the given hash.
-
.values_from_list(raw_key) ⇒ Object
Returns the values of the given list.
-
.values_from_set(raw_key) ⇒ Object
Returns the values of the given set.
- .with_redis(&block) ⇒ Object
-
.write(raw_key, value, timeout: TIMEOUT) ⇒ Object
Sets a cache key to the given value.
-
.write_if_greater(raw_key, value, timeout: TIMEOUT) ⇒ Object
Sets a key to the given integer but only if the existing value is smaller than the given value.
-
.write_multiple(mapping, key_prefix: nil, timeout: TIMEOUT) ⇒ Object
Sets multiple keys to given values.
Class Method Details
.cache_key_for(raw_key) ⇒ Object
352 353 354 |
# File 'lib/gitlab/cache/import/caching.rb', line 352 def self.cache_key_for(raw_key) "#{Redis::Cache::CACHE_NAMESPACE}:#{raw_key}" end |
.del(raw_key) ⇒ Object
Deletes a key
raw_key - Key name
344 345 346 347 348 349 350 |
# File 'lib/gitlab/cache/import/caching.rb', line 344 def self.del(raw_key) key = cache_key_for(raw_key) with_redis do |redis| redis.del(key) end end |
.expire(raw_key, timeout) ⇒ Object
Sets the expiration time of a key.
raw_key - The key for which to change the timeout. timeout - The new timeout.
217 218 219 220 221 222 223 |
# File 'lib/gitlab/cache/import/caching.rb', line 217 def self.expire(raw_key, timeout) key = cache_key_for(raw_key) with_redis do |redis| redis.expire(key, timeout) end end |
.hash_add(raw_key, field, value, timeout: TIMEOUT) ⇒ Object
Adds a value to a hash.
raw_key - The key of the hash to add to. field - The field to add to the hash. value - The field value to add to the hash. timeout - The new timeout of the key.
253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/gitlab/cache/import/caching.rb', line 253 def self.hash_add(raw_key, field, value, timeout: TIMEOUT) validate_redis_value!(value) key = cache_key_for(raw_key) with_redis do |redis| redis.multi do |m| m.hset(key, field, value) m.expire(key, timeout) end end end |
.hash_increment(raw_key, field, value, timeout: TIMEOUT) ⇒ Object
Increments value of a field in a hash
raw_key - The key of the hash to add to. field - The field to increment. value - The field value to add to the hash. timeout - The new timeout of the key.
297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/gitlab/cache/import/caching.rb', line 297 def self.hash_increment(raw_key, field, value, timeout: TIMEOUT) return if value.to_i <= 0 key = cache_key_for(raw_key) with_redis do |redis| redis.multi do |m| m.hincrby(key, field, value.to_i) m.expire(key, timeout) end end end |
.increment(raw_key, timeout: TIMEOUT) ⇒ Object
Increment the integer value of a key by one. Sets the value to zero if missing before incrementing
raw_key - The cache key to increment. timeout - The time after which the cache key should expire.
85 86 87 88 89 90 91 92 93 94 |
# File 'lib/gitlab/cache/import/caching.rb', line 85 def self.increment(raw_key, timeout: TIMEOUT) key = cache_key_for(raw_key) with_redis do |redis| value = redis.incr(key) redis.expire(key, timeout) value end end |
.increment_by(raw_key, value, timeout: TIMEOUT) ⇒ Object
Increment the integer value of a key by the given value. Sets the value to zero if missing before incrementing
raw_key - The cache key to increment. value - The value to increment the key timeout - The time after which the cache key should expire.
103 104 105 106 107 108 109 110 111 112 |
# File 'lib/gitlab/cache/import/caching.rb', line 103 def self.increment_by(raw_key, value, timeout: TIMEOUT) validate_redis_value!(value) key = cache_key_for(raw_key) with_redis do |redis| redis.incrby(key, value) redis.expire(key, timeout) end end |
.limited_values_from_set(raw_key, limit: 1) ⇒ Object
Returns a limited number of random values from the set.
raw_key - The key of the set to check. limit - Number of values to return (default: 1).
172 173 174 175 176 177 178 |
# File 'lib/gitlab/cache/import/caching.rb', line 172 def self.limited_values_from_set(raw_key, limit: 1) key = cache_key_for(raw_key) with_redis do |redis| redis.srandmember(key, limit) end end |
.list_add(raw_key, value, timeout: TIMEOUT, limit: nil) ⇒ Object
Adds a value to a list.
raw_key - The key of the list to add to. value - The field value to add to the list. timeout - The new timeout of the key. limit - The maximum number of members in the list. Older members will be trimmed to this limit.
316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/gitlab/cache/import/caching.rb', line 316 def self.list_add(raw_key, value, timeout: TIMEOUT, limit: nil) validate_redis_value!(value) key = cache_key_for(raw_key) with_redis do |redis| redis.multi do |m| m.rpush(key, value) m.ltrim(key, -limit, -1) if limit m.expire(key, timeout) end end end |
.read(raw_key, timeout: TIMEOUT) ⇒ Object
Reads a cache key.
If the key exists and has a non-empty value its TTL is refreshed automatically.
raw_key - The cache key to read. timeout - The new timeout of the key if the key is to be refreshed.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/gitlab/cache/import/caching.rb', line 34 def self.read(raw_key, timeout: TIMEOUT) key = cache_key_for(raw_key) value = with_redis { |redis| redis.get(key) } if value.present? # We refresh the expiration time so frequently used keys stick # around, removing the need for querying the database as much as # possible. # # A key may be empty when we looked up a GitHub user (for example) but # did not find a matching GitLab user. In that case we _don't_ want to # refresh the TTL so we automatically pick up the right data when said # user were to register themselves on the GitLab instance. with_redis { |redis| redis.expire(key, timeout) } end value end |
.read_integer(raw_key, timeout: TIMEOUT) ⇒ Object
Reads an integer from the cache, or returns nil if no value was found.
See Caching.read for more information.
56 57 58 59 60 |
# File 'lib/gitlab/cache/import/caching.rb', line 56 def self.read_integer(raw_key, timeout: TIMEOUT) value = read(raw_key, timeout: timeout) value.to_i if value.present? end |
.set_add(raw_key, value, timeout: TIMEOUT) ⇒ Object
Adds a value to a set.
raw_key - The key of the set to add the value to. value - The value to add to the set. timeout - The new timeout of the key.
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/gitlab/cache/import/caching.rb', line 119 def self.set_add(raw_key, value, timeout: TIMEOUT) validate_redis_value!(value) key = cache_key_for(raw_key) with_redis do |redis| redis.multi do |m| m.sadd?(key, value) m.expire(key, timeout) end end end |
.set_count(raw_key) ⇒ Object
Returns the number of values in the set.
raw_key - The key of the set to check.
149 150 151 152 153 154 155 |
# File 'lib/gitlab/cache/import/caching.rb', line 149 def self.set_count(raw_key) key = cache_key_for(raw_key) with_redis do |redis| redis.scard(key) end end |
.set_includes?(raw_key, value) ⇒ Boolean
Returns true if the given value is present in the set.
raw_key - The key of the set to check. value - The value to check for.
136 137 138 139 140 141 142 143 144 |
# File 'lib/gitlab/cache/import/caching.rb', line 136 def self.set_includes?(raw_key, value) validate_redis_value!(value) key = cache_key_for(raw_key) with_redis do |redis| redis.sismember(key, value || value.to_s) end end |
.set_remove(raw_key, values = []) ⇒ Object
Removes the given values from the set.
raw_key - The key of the set to check. values - Array of values to remove from set.
184 185 186 187 188 189 190 |
# File 'lib/gitlab/cache/import/caching.rb', line 184 def self.set_remove(raw_key, values = []) key = cache_key_for(raw_key) with_redis do |redis| redis.srem(key, values) end end |
.validate_redis_value!(value) ⇒ Object
360 361 362 363 364 365 |
# File 'lib/gitlab/cache/import/caching.rb', line 360 def self.validate_redis_value!(value) value_as_string = value.to_s return if value_as_string.is_a?(String) raise "Value '#{value_as_string}' of type '#{value_as_string.class}' for '#{value.inspect}' is not a String" end |
.value_from_hash(raw_key, field, timeout: TIMEOUT) ⇒ Object
Returns a single value of the given hash.
raw_key - The key of the hash to check. field - The field to get from the hash.
281 282 283 284 285 286 287 288 289 |
# File 'lib/gitlab/cache/import/caching.rb', line 281 def self.value_from_hash(raw_key, field, timeout: TIMEOUT) key = cache_key_for(raw_key) value = with_redis { |redis| redis.hget(key, field) } with_redis { |redis| redis.expire(key, timeout) } if value.present? value end |
.values_from_hash(raw_key) ⇒ Object
Returns the values of the given hash.
raw_key - The key of the hash to check.
269 270 271 272 273 274 275 |
# File 'lib/gitlab/cache/import/caching.rb', line 269 def self.values_from_hash(raw_key) key = cache_key_for(raw_key) with_redis do |redis| redis.hgetall(key) end end |
.values_from_list(raw_key) ⇒ Object
Returns the values of the given list.
raw_key - The key of the list.
333 334 335 336 337 338 339 |
# File 'lib/gitlab/cache/import/caching.rb', line 333 def self.values_from_list(raw_key) key = cache_key_for(raw_key) with_redis do |redis| redis.lrange(key, 0, -1) end end |
.values_from_set(raw_key) ⇒ Object
Returns the values of the given set.
raw_key - The key of the set to check.
160 161 162 163 164 165 166 |
# File 'lib/gitlab/cache/import/caching.rb', line 160 def self.values_from_set(raw_key) key = cache_key_for(raw_key) with_redis do |redis| redis.smembers(key) end end |
.with_redis(&block) ⇒ Object
356 357 358 |
# File 'lib/gitlab/cache/import/caching.rb', line 356 def self.with_redis(&block) Gitlab::Redis::SharedState.with(&block) # rubocop:disable CodeReuse/ActiveRecord -- This is not AR end |
.write(raw_key, value, timeout: TIMEOUT) ⇒ Object
Sets a cache key to the given value.
raw_key - The cache key to write. value - The value to set. timeout - The time after which the cache key should expire.
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/gitlab/cache/import/caching.rb', line 67 def self.write(raw_key, value, timeout: TIMEOUT) validate_redis_value!(value) key = cache_key_for(raw_key) with_redis do |redis| redis.set(key, value, ex: timeout) end value end |
.write_if_greater(raw_key, value, timeout: TIMEOUT) ⇒ Object
Sets a key to the given integer but only if the existing value is smaller than the given value.
This method uses a Lua script to ensure the read and write are atomic.
raw_key - The key to set. value - The new value for the key. timeout - The key timeout in seconds.
Returns true when the key was overwritten, false otherwise.
235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/gitlab/cache/import/caching.rb', line 235 def self.write_if_greater(raw_key, value, timeout: TIMEOUT) validate_redis_value!(value) key = cache_key_for(raw_key) val = with_redis do |redis| redis .eval(WRITE_IF_GREATER_SCRIPT, keys: [key], argv: [value, timeout]) end val ? true : false end |
.write_multiple(mapping, key_prefix: nil, timeout: TIMEOUT) ⇒ Object
Sets multiple keys to given values.
mapping - A Hash mapping the cache keys to their values. key_prefix - prefix inserted before each key timeout - The time after which the cache key should expire.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/gitlab/cache/import/caching.rb', line 197 def self.write_multiple(mapping, key_prefix: nil, timeout: TIMEOUT) with_redis do |redis| Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do redis.pipelined do |pipeline| mapping.each do |raw_key, value| key = cache_key_for("#{key_prefix}#{raw_key}") validate_redis_value!(value) pipeline.set(key, value, ex: timeout) end end end end end |