def test(test_name, alternatives, options = {})
short_circuit = Abingo.cache.read("Abingo::Experiment::short_circuit(#{test_name})".gsub(" ", "_"))
unless short_circuit.nil?
return short_circuit
end
unless Abingo::Experiment.exists?(test_name)
lock_key = "Abingo::lock_for_creation(#{test_name.gsub(" ", "_")})"
lock_id = SecureRandom.hex
if Abingo.cache.exist?(lock_key)
wait_for_lock_release(lock_key)
else
Abingo.cache.write(lock_key, lock_id, :expires_in => 5.seconds)
sleep(0.1)
if Abingo.cache.read(lock_key) == lock_id
conversion_name = options[:conversion] || options[:conversion_name]
Abingo::Experiment.start_experiment!(test_name, Abingo.parse_alternatives(alternatives), conversion_name)
else
wait_for_lock_release(lock_key)
end
end
Abingo.cache.delete(lock_key)
end
choice = self.find_alternative_for_user(test_name, alternatives)
participating_tests = Abingo.cache.read("Abingo::participating_tests::#{self.identity}") || []
if options[:multiple_participation] || !(participating_tests.include?(test_name))
unless participating_tests.include?(test_name)
participating_tests = participating_tests + [test_name]
if self.expires_in
Abingo.cache.write("Abingo::participating_tests::#{self.identity}", participating_tests, {:expires_in => self.expires_in})
else
Abingo.cache.write("Abingo::participating_tests::#{self.identity}", participating_tests)
end
end
if (!@@options[:count_humans_only] || self.is_human?)
Abingo::Alternative.score_participation(test_name, choice)
end
end
if block_given?
yield(choice)
else
choice
end
end