File: cache.rb

package info (click to toggle)
ruby-gitlab-experiment 0.9.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 260 kB
  • sloc: ruby: 1,202; makefile: 7
file content (76 lines) | stat: -rw-r--r-- 1,923 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# frozen_string_literal: true

module Gitlab
  class Experiment
    module Cache
      autoload :RedisHashStore, 'gitlab/experiment/cache/redis_hash_store.rb'

      class Interface
        attr_reader :store, :key

        def initialize(experiment, store)
          @experiment = experiment
          @store = store
          @key = experiment.cache_key
        end

        def read
          store.read(key)
        end

        def write(value = nil)
          store.write(key, value || @experiment.assigned.name)
        end

        def delete
          store.delete(key)
        end

        def attr_get(name)
          store.read(@experiment.cache_key(name, suffix: :attrs))
        end

        def attr_set(name, value)
          store.write(@experiment.cache_key(name, suffix: :attrs), value)
        end

        def attr_inc(name, amount = 1)
          store.increment(@experiment.cache_key(name, suffix: :attrs), amount)
        end
      end

      def cache
        @cache ||= Interface.new(self, Configuration.cache)
      end

      def cache_variant(specified = nil, &block)
        return (specified.presence || yield) unless cache.store

        result = migrated_cache_fetch(cache.store, &block)
        return result unless specified.present?

        cache.write(specified) if result.to_s != specified.to_s
        specified
      end

      def cache_key(key = nil, suffix: nil)
        "#{[name, suffix].compact.join('_')}:#{key || context.signature[:key]}"
      end

      private

      def migrated_cache_fetch(store, &block)
        migrations = context.signature[:migration_keys]&.map { |key| cache_key(key) } || []
        migrations.find do |old_key|
          value = store.read(old_key)

          next unless value

          store.write(cache_key, value)
          store.delete(old_key)
          break value
        end || store.fetch(cache_key, &block)
      end
    end
  end
end