From 6d8da6f935492dee362f15d55b3e2fe88f4e42b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Luis=20Leal=20Cardoso=20Junior?= Date: Sun, 19 Jul 2026 15:02:43 -0300 Subject: [PATCH 1/2] Drop redundant exists? roundtrip in Experiment.find --- lib/split/experiment.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/split/experiment.rb b/lib/split/experiment.rb index d91552da..f9854587 100644 --- a/lib/split/experiment.rb +++ b/lib/split/experiment.rb @@ -18,8 +18,9 @@ class Experiment def self.find(name) Split.cache(:experiments, name) do - return unless Split.redis.exists?(name) - Experiment.new(name).tap { |exp| exp.load_from_redis } + experiment = Experiment.new(name) + experiment.load_from_redis + experiment unless experiment.alternatives.empty? end end From ae2812d1fe2e1fb065d9289614a85f004d47b85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Luis=20Leal=20Cardoso=20Junior?= Date: Sun, 19 Jul 2026 15:04:12 -0300 Subject: [PATCH 2/2] Pipeline experiment load into a single Redis roundtrip --- lib/split/experiment_storage.rb | 54 ++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/split/experiment_storage.rb b/lib/split/experiment_storage.rb index d073adfc..96bb76fa 100644 --- a/lib/split/experiment_storage.rb +++ b/lib/split/experiment_storage.rb @@ -80,29 +80,22 @@ def exists? redis.exists?(@name) end - def load_alternatives - alternatives = redis.lrange(@name, 0, -1) - alternatives.map do |alt| - alt = begin - JSON.parse(alt) - rescue - alt - end - Split::Alternative.new(alt, @name) + def load! + raw_config, raw_alternatives, raw_metadata, raw_goals = redis.pipelined do |pipe| + pipe.hgetall(experiment_config_key) + pipe.lrange(@name, 0, -1) + pipe.get(metadata_key) + pipe.lrange(goals_key, 0, -1) end - end - - def load_metadata - meta = redis.get(metadata_key) - JSON.parse(meta) unless meta.nil? - end - - def load_goals - Split::GoalsCollection.new(@name).load_from_redis - end + config = raw_config.transform_keys(&:to_sym) - def load_experiment - redis.hgetall(experiment_config_key).transform_keys(&:to_sym) + { + resettable: config[:resettable], + algorithm: config[:algorithm], + alternatives: build_alternatives(raw_alternatives), + goals: raw_goals, + metadata: parse_metadata(raw_metadata) + } end def experiment_config_key @@ -113,10 +106,29 @@ def metadata_key "#{name}:metadata" end + def goals_key + "#{name}:goals" + end + private def redis Split.redis end + + def build_alternatives(raw_alternatives) + raw_alternatives.map do |alt| + alt = begin + JSON.parse(alt) + rescue + alt + end + Split::Alternative.new(alt, @name) + end + end + + def parse_metadata(raw_metadata) + JSON.parse(raw_metadata) unless raw_metadata.nil? + end end end end