# frozen_string_literal: true

# The random rollout strategy will randomly assign a variant when the context is determined to be within the experiment
# group.
#
# If caching is enabled this is a predictable and consistent assignment that will eventually assign a non-control
# variant. This relies on the strategy intentionally NOT caching control assignments -- so when a context is sampled
# into control, it gets re-rolled on the next visit until it lands on a non-control variant, at which point the
# assignment is cached and stable. Without caching, assignment is random on every call.
#
# This is the only rollout that opts out of caching control: every other rollout caches whatever variant it resolves to.
# Example configuration usage:
#
# config.default_rollout = Gitlab::Experiment::Rollout::Random.new
#
# Example class usage:
#
# class PillColorExperiment < ApplicationExperiment
#   control { }
#   variant(:red) { }
#   variant(:blue) { }
#
#   # Randomize between all behaviors, with a mostly even distribution).
#   default_rollout :random
# end
#
module Gitlab
  class Experiment
    module Rollout
      class Random < Base
        protected

        def execute_assignment
          result = behavior_names.sample # pick a random variant
          # Drop :control so it's never cached, even if cache_control is true.
          # The context will be re-rolled on the next visit and eventually converge on a non-control variant.
          result == :control ? nil : result
        end
      end
    end
  end
end
