From a4f036a2619dabf29ed6fe532829d1801941479f Mon Sep 17 00:00:00 2001 From: Christopher Pang Date: Wed, 20 Jul 2022 17:36:59 -0700 Subject: [PATCH 1/3] created mysql adapter --- lib/split/experiment.rb | 3 + lib/split/helper.rb | 22 +++++++ lib/split/persistence.rb | 1 + lib/split/persistence/mysql_adapter.rb | 90 ++++++++++++++++++++++++++ lib/split/persistence/redis_adapter.rb | 1 + lib/split/redis_interface.rb | 8 +++ lib/split/trial.rb | 18 +++++- 7 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 lib/split/persistence/mysql_adapter.rb diff --git a/lib/split/experiment.rb b/lib/split/experiment.rb index befdf3d5..7037997c 100644 --- a/lib/split/experiment.rb +++ b/lib/split/experiment.rb @@ -90,6 +90,9 @@ def save redis.hset(experiment_config_key, :retain_user_alternatives_after_reset, retain_user_alternatives_after_reset) redis.hset(experiment_config_key, :resettable, resettable) redis.hset(experiment_config_key, :algorithm, algorithm.to_s) + + #binding.pry + self end diff --git a/lib/split/helper.rb b/lib/split/helper.rb index 4e53a5ec..a3ea602d 100644 --- a/lib/split/helper.rb +++ b/lib/split/helper.rb @@ -7,14 +7,36 @@ module Helper def ab_test(metric_descriptor, control = nil, *alternatives) begin + + # here is where ab_test gets called + #binding.pry + + experiment = ExperimentCatalog.find_or_initialize(metric_descriptor, control, *alternatives) alternative = if Split.configuration.enabled && !exclude_visitor? + + # this is usually true + experiment.save + + #binding.pry + + raise(Split::InvalidExperimentsFormatError) unless (Split.configuration.experiments || {}).fetch(experiment.name.to_sym, {})[:combined_experiments].nil? + + #binding.pry + trial = Trial.new(:user => ab_user, :experiment => experiment, :override => override_alternative(experiment.name), :exclude => !is_qualified?, :disabled => split_generically_disabled?) + + #binding.pry + + # THIS IS THE STEP WHERE THE PERSISTENCE OBJECT GETS CREATED alt = trial.choose!(self) + + #binding.pry + alt ? alt.name : nil else control_variable(experiment.control) diff --git a/lib/split/persistence.rb b/lib/split/persistence.rb index a464c463..dbfdaf70 100644 --- a/lib/split/persistence.rb +++ b/lib/split/persistence.rb @@ -6,6 +6,7 @@ module Persistence require 'split/persistence/dual_adapter' require 'split/persistence/redis_adapter' require 'split/persistence/session_adapter' + require 'split/persistence/mysql_adapter' ADAPTERS = { :cookie => Split::Persistence::CookieAdapter, diff --git a/lib/split/persistence/mysql_adapter.rb b/lib/split/persistence/mysql_adapter.rb new file mode 100644 index 00000000..1cbc2507 --- /dev/null +++ b/lib/split/persistence/mysql_adapter.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true +module Split + module Persistence + class MysqlAdapter + DEFAULT_CONFIG = {:namespace => 'persistence'}.freeze + + attr_reader :account_id + + def initialize(context, acc_id = nil) + # Split::Persistence.adapter.new(nil, 347381).test_create_or_update('exp123:1', 'control') + if acc_id + @account_id = acc_id + elsif lookup_by = self.class.config[:lookup_by] + if lookup_by.respond_to?(:call) + key_frag = lookup_by.call(context) + else + key_frag = context.send(lookup_by) + end + @account_id = key_frag + else + raise "Please configure lookup_by" + end + end + + #-------------- + + def test_get(property) + search_for_record(property) + end + + def test_create_or_update(property, value) + record = Manage::ExperimentPersistence.where( + experiment_id: experiment_id_parser(property), + account_id: account_id, + property: property + ).first_or_initialize + record.update!(value: value); + end + + #------------- + + def [](property) + search_for_record(property) + end + + def []=(property, value) + record = Manage::ExperimentPersistence.where( + experiment_id: experiment_id_parser(property), + account_id: account_id, + property: property + ).first_or_initialize + record.update!(value: value); + end + + def delete(field) + record_to_delete = search_for_record(property) + record_to_delete.destroy! + end + + # -------- + + def keys + Split.redis.hkeys(redis_key) + end + + def self.with_config(options={}) + self.config.merge!(options) + self + end + + def self.config + @config ||= DEFAULT_CONFIG.dup + end + + def self.reset_config! + @config = DEFAULT_CONFIG.dup + end + + def experiment_id_parser(property) + property.split(":").first + end + + def search_for_record(property) + Manage::ExperimentPersistence.find_by(experiment_id: experiment_id_parser(property), property: property, account_id: account_id) + end + + + end + end +end diff --git a/lib/split/persistence/redis_adapter.rb b/lib/split/persistence/redis_adapter.rb index 3fe367b9..e686f7e6 100644 --- a/lib/split/persistence/redis_adapter.rb +++ b/lib/split/persistence/redis_adapter.rb @@ -7,6 +7,7 @@ class RedisAdapter attr_reader :redis_key def initialize(context, key = nil) + binding.pry if key @redis_key = "#{self.class.config[:namespace]}:#{key}" elsif lookup_by = self.class.config[:lookup_by] diff --git a/lib/split/redis_interface.rb b/lib/split/redis_interface.rb index 1796a980..cebd24dc 100644 --- a/lib/split/redis_interface.rb +++ b/lib/split/redis_interface.rb @@ -7,6 +7,8 @@ def initialize end def persist_list(list_name, list_values) + binding.pry + max_index = list_length(list_name) - 1 list_values.each_with_index do |value, index| if index > max_index @@ -20,6 +22,8 @@ def persist_list(list_name, list_values) end def add_to_list(list_name, value) + binding.pry + redis.rpush(list_name, value) end @@ -32,6 +36,8 @@ def list_length(list_name) end def remove_last_item_from_list(list_name) + binding.pry + redis.rpop(list_name) end @@ -40,6 +46,8 @@ def make_list_length(list_name, new_length) end def add_to_set(set_name, value) + binding.pry + redis.sadd(set_name, value) unless redis.sismember(set_name, value) end diff --git a/lib/split/trial.rb b/lib/split/trial.rb index c561e36a..9907aedd 100644 --- a/lib/split/trial.rb +++ b/lib/split/trial.rb @@ -55,13 +55,19 @@ def complete!(context = nil) # method is guaranteed to only run once, and will skip the alternative choosing process if run # a second time. def choose!(context = nil) + @user.cleanup_old_experiments! # Only run the process once + return alternative if @alternative_choosen + user_experiment_key = @experiment.retain_user_alternatives_after_reset ? @user.alternative_key_for_experiment(@experiment) : @experiment.key new_participant = @user[user_experiment_key].nil? if override_is_alternative? + + + self.alternative = @options[:override] if should_store_alternative? && !@user[user_experiment_key] self.alternative.increment_participation @@ -72,11 +78,11 @@ def choose!(context = nil) self.alternative = @experiment.winner else cleanup_old_versions unless experiment.retain_user_alternatives_after_reset - if exclude_user? self.alternative = @experiment.control else self.alternative = @user[user_experiment_key] + if alternative.nil? if @experiment.cohorting_disabled? self.alternative = @experiment.control @@ -86,18 +92,27 @@ def choose!(context = nil) # Increment the number of participants since we are actually choosing a new alternative self.alternative.increment_participation + binding.pry + save_time_that_user_is_assigned + + binding.pry + run_callback context, Split.configuration.on_trial_choose end end end end + binding.pry + new_participant_and_cohorting_disabled = new_participant && @experiment.cohorting_disabled? @user[user_experiment_key] = alternative.name unless @experiment.has_winner? || !should_store_alternative? || new_participant_and_cohorting_disabled + @alternative_choosen = true run_callback context, Split.configuration.on_trial unless @options[:disabled] || Split.configuration.disabled? || new_participant_and_cohorting_disabled + alternative end @@ -133,6 +148,7 @@ def delete_experiment_context_keys end def save_time_that_user_is_assigned + binding.pry @user["#{user_experiment_key}:time_of_assignment"] = Time.now.to_s end From 329dc8c62f43363a31fdcede82dbbeda0ca685f1 Mon Sep 17 00:00:00 2001 From: Christopher Pang Date: Thu, 21 Jul 2022 13:07:14 -0700 Subject: [PATCH 2/3] removed testing prys --- lib/split/experiment.rb | 2 -- lib/split/helper.rb | 20 -------------------- lib/split/persistence/redis_adapter.rb | 1 - lib/split/redis_interface.rb | 10 +--------- lib/split/trial.rb | 8 -------- 5 files changed, 1 insertion(+), 40 deletions(-) diff --git a/lib/split/experiment.rb b/lib/split/experiment.rb index 7037997c..0bdd931b 100644 --- a/lib/split/experiment.rb +++ b/lib/split/experiment.rb @@ -91,8 +91,6 @@ def save redis.hset(experiment_config_key, :resettable, resettable) redis.hset(experiment_config_key, :algorithm, algorithm.to_s) - #binding.pry - self end diff --git a/lib/split/helper.rb b/lib/split/helper.rb index a3ea602d..6064ce55 100644 --- a/lib/split/helper.rb +++ b/lib/split/helper.rb @@ -7,36 +7,16 @@ module Helper def ab_test(metric_descriptor, control = nil, *alternatives) begin - - # here is where ab_test gets called - #binding.pry - - experiment = ExperimentCatalog.find_or_initialize(metric_descriptor, control, *alternatives) alternative = if Split.configuration.enabled && !exclude_visitor? - - # this is usually true - experiment.save - - #binding.pry - - raise(Split::InvalidExperimentsFormatError) unless (Split.configuration.experiments || {}).fetch(experiment.name.to_sym, {})[:combined_experiments].nil? - #binding.pry - trial = Trial.new(:user => ab_user, :experiment => experiment, :override => override_alternative(experiment.name), :exclude => !is_qualified?, :disabled => split_generically_disabled?) - #binding.pry - - # THIS IS THE STEP WHERE THE PERSISTENCE OBJECT GETS CREATED alt = trial.choose!(self) - - #binding.pry - alt ? alt.name : nil else control_variable(experiment.control) diff --git a/lib/split/persistence/redis_adapter.rb b/lib/split/persistence/redis_adapter.rb index e686f7e6..3fe367b9 100644 --- a/lib/split/persistence/redis_adapter.rb +++ b/lib/split/persistence/redis_adapter.rb @@ -7,7 +7,6 @@ class RedisAdapter attr_reader :redis_key def initialize(context, key = nil) - binding.pry if key @redis_key = "#{self.class.config[:namespace]}:#{key}" elsif lookup_by = self.class.config[:lookup_by] diff --git a/lib/split/redis_interface.rb b/lib/split/redis_interface.rb index cebd24dc..0a55a1b8 100644 --- a/lib/split/redis_interface.rb +++ b/lib/split/redis_interface.rb @@ -7,8 +7,6 @@ def initialize end def persist_list(list_name, list_values) - binding.pry - max_index = list_length(list_name) - 1 list_values.each_with_index do |value, index| if index > max_index @@ -22,8 +20,6 @@ def persist_list(list_name, list_values) end def add_to_list(list_name, value) - binding.pry - redis.rpush(list_name, value) end @@ -36,8 +32,6 @@ def list_length(list_name) end def remove_last_item_from_list(list_name) - binding.pry - redis.rpop(list_name) end @@ -46,10 +40,8 @@ def make_list_length(list_name, new_length) end def add_to_set(set_name, value) - binding.pry - redis.sadd(set_name, value) unless redis.sismember(set_name, value) - end + end`` private diff --git a/lib/split/trial.rb b/lib/split/trial.rb index 9907aedd..fbcc607f 100644 --- a/lib/split/trial.rb +++ b/lib/split/trial.rb @@ -66,8 +66,6 @@ def choose!(context = nil) new_participant = @user[user_experiment_key].nil? if override_is_alternative? - - self.alternative = @options[:override] if should_store_alternative? && !@user[user_experiment_key] self.alternative.increment_participation @@ -92,19 +90,14 @@ def choose!(context = nil) # Increment the number of participants since we are actually choosing a new alternative self.alternative.increment_participation - binding.pry - save_time_that_user_is_assigned - binding.pry - run_callback context, Split.configuration.on_trial_choose end end end end - binding.pry new_participant_and_cohorting_disabled = new_participant && @experiment.cohorting_disabled? @@ -148,7 +141,6 @@ def delete_experiment_context_keys end def save_time_that_user_is_assigned - binding.pry @user["#{user_experiment_key}:time_of_assignment"] = Time.now.to_s end From 4e7deb835dd10f03087a6e87d1a7d670157f6e9b Mon Sep 17 00:00:00 2001 From: Christopher Pang Date: Thu, 21 Jul 2022 14:00:54 -0700 Subject: [PATCH 3/3] removed semi colons --- lib/split/persistence/mysql_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/split/persistence/mysql_adapter.rb b/lib/split/persistence/mysql_adapter.rb index 1cbc2507..bf44aa80 100644 --- a/lib/split/persistence/mysql_adapter.rb +++ b/lib/split/persistence/mysql_adapter.rb @@ -34,7 +34,7 @@ def test_create_or_update(property, value) account_id: account_id, property: property ).first_or_initialize - record.update!(value: value); + record.update!(value: value) end #------------- @@ -49,7 +49,7 @@ def []=(property, value) account_id: account_id, property: property ).first_or_initialize - record.update!(value: value); + record.update!(value: value) end def delete(field)