set_cache.rb 1.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# frozen_string_literal: true

# Interface to the Redis-backed cache store to keep track of complete cache keys
# for a ReactiveCache resource.
module Gitlab
  class SetCache
    attr_reader :expires_in

    def initialize(expires_in: 2.weeks)
      @expires_in = expires_in
    end

    def cache_key(key)
      "#{key}:set"
    end

17
    # Returns the number of keys deleted by Redis
18
    def expire(*keys)
19 20
      return 0 if keys.empty?

21 22 23 24
      with do |redis|
        keys = keys.map { |key| cache_key(key) }
        unlink_or_delete(redis, keys)
      end
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
    end

    def exist?(key)
      with { |redis| redis.exists(cache_key(key)) }
    end

    def write(key, value)
      with do |redis|
        redis.pipelined do
          redis.sadd(cache_key(key), value)

          redis.expire(cache_key(key), expires_in)
        end
      end

      value
    end

    def read(key)
      with { |redis| redis.smembers(cache_key(key)) }
    end

    def include?(key, value)
      with { |redis| redis.sismember(cache_key(key), value) }
    end

    def ttl(key)
      with { |redis| redis.ttl(cache_key(key)) }
    end

    private

    def with(&blk)
      Gitlab::Redis::Cache.with(&blk) # rubocop:disable CodeReuse/ActiveRecord
    end
60 61 62 63 64 65 66 67 68 69

    def unlink_or_delete(redis, keys)
      if Feature.enabled?(:repository_set_cache_unlink, default_enabled: true)
        redis.unlink(*keys)
      else
        redis.del(*keys)
      end
    rescue ::Redis::CommandError
      redis.del(*keys)
    end
70 71
  end
end