File: rollout.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 (69 lines) | stat: -rw-r--r-- 1,764 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
# frozen_string_literal: true

module Gitlab
  class Experiment
    module Rollout
      autoload :Percent, 'gitlab/experiment/rollout/percent.rb'
      autoload :Random, 'gitlab/experiment/rollout/random.rb'
      autoload :RoundRobin, 'gitlab/experiment/rollout/round_robin.rb'

      def self.resolve(klass, options = {})
        options ||= {}
        case klass
        when String
          Strategy.new(klass.classify.constantize, options)
        when Symbol
          Strategy.new("#{name}::#{klass.to_s.classify}".constantize, options)
        when Class
          Strategy.new(klass, options)
        else
          raise ArgumentError, "unable to resolve rollout from #{klass.inspect}"
        end
      end

      class Base
        attr_reader :experiment, :options

        delegate :cache, :id, to: :experiment

        def initialize(experiment, options = {})
          raise ArgumentError, 'you must provide an experiment instance' unless experiment.class <= Gitlab::Experiment

          @experiment = experiment
          @options = options
        end

        def enabled?
          true
        end

        def resolve
          validate! # allow the rollout strategy to validate itself

          assignment = execute_assignment
          assignment == :control ? nil : assignment # avoid caching control by returning nil
        end

        private

        def validate!
          # base is always valid
        end

        def execute_assignment
          behavior_names.first
        end

        def behavior_names
          experiment.behaviors.keys
        end
      end

      Strategy = Struct.new(:klass, :options) do
        def for(experiment)
          klass.new(experiment, options)
        end
      end
    end
  end
end