Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/optimizely.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ def decide(user_context, key, decide_options = [])
decision_event_dispatched = false
experiment = nil
decision_source = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']

variation, reasons_received = user_context.find_validated_forced_decision(key, nil)
context = Optimizely::OptimizelyUserContext::OptimizelyDecisionContext.new(key, nil)
variation, reasons_received = user_context.find_validated_forced_decision(context)
reasons.push(*reasons_received)

if variation
Expand Down
6 changes: 4 additions & 2 deletions lib/optimizely/decision_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ def get_variation_from_experiment_rule(project_config, flag_key, rule, user, opt
# Returns variation_id and reasons
reasons = []

variation, forced_reasons = user.find_validated_forced_decision(flag_key, rule['key'])
context = Optimizely::OptimizelyUserContext::OptimizelyDecisionContext.new(flag_key, rule['key'])
variation, forced_reasons = user.find_validated_forced_decision(context)
reasons.push(*forced_reasons)

return [variation['id'], reasons] if variation
Expand All @@ -287,7 +288,8 @@ def get_variation_from_delivery_rule(project_config, flag_key, rules, rule_index
reasons = []
skip_to_everyone_else = false
rule = rules[rule_index]
variation, forced_reasons = user.find_validated_forced_decision(flag_key, rule['key'])
context = Optimizely::OptimizelyUserContext::OptimizelyDecisionContext.new(flag_key, rule['key'])
variation, forced_reasons = user.find_validated_forced_decision(context)
reasons.push(*forced_reasons)

return [variation, skip_to_everyone_else, reasons] if variation
Expand Down
52 changes: 26 additions & 26 deletions lib/optimizely/optimizely_user_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ class OptimizelyUserContext

attr_reader :user_id
attr_reader :forced_decisions
attr_reader :ForcedDecision
attr_reader :OptimizelyDecisionContext
attr_reader :OptimizelyForcedDecision

ForcedDecision = Struct.new(:flag_key, :rule_key)
OptimizelyDecisionContext = Struct.new(:flag_key, :rule_key)
OptimizelyForcedDecision = Struct.new(:variation_key)
def initialize(optimizely_client, user_id, user_attributes)
@attr_mutex = Mutex.new
@forced_decision_mutex = Mutex.new
Expand Down Expand Up @@ -94,59 +96,54 @@ def decide_all(options = nil)

# Sets the forced decision (variation key) for a given flag and an optional rule.
#
# @param flag_key - A flag key.
# @param rule_key - An experiment or delivery rule key (optional).
# @param variation_key - A variation key.
# @param context - An OptimizelyDecisionContext object containg flag key and rule key.
# @param decision - An OptimizelyForcedDecision object containing variation key
#
# @return - true if the forced decision has been set successfully.

def set_forced_decision(flag_key, rule_key, variation_key)
def set_forced_decision(context, decision)
flag_key = context[:flag_key]
return false if @optimizely_client&.get_optimizely_config.nil?
return false if flag_key.empty? || flag_key.nil?
return false if flag_key.nil?

forced_decision_key = ForcedDecision.new(flag_key, rule_key)
@forced_decision_mutex.synchronize { @forced_decisions[forced_decision_key] = variation_key }
@forced_decision_mutex.synchronize { @forced_decisions[context] = decision }

true
end

def find_forced_decision(flag_key, rule_key = nil)
def find_forced_decision(context)
return nil if @forced_decisions.empty?

variation_key = nil
forced_decision_key = ForcedDecision.new(flag_key, rule_key)
@forced_decision_mutex.synchronize { variation_key = @forced_decisions[forced_decision_key] }
variation_key
decision = nil
@forced_decision_mutex.synchronize { decision = @forced_decisions[context] }
decision
end

# Returns the forced decision for a given flag and an optional rule.
#
# @param flag_key - A flag key.
# @param rule_key - An experiment or delivery rule key (optional).
# @param context - An OptimizelyDecisionContext object containg flag key and rule key.
#
# @return - A variation key or nil if forced decisions are not set for the parameters.

def get_forced_decision(flag_key, rule_key = nil)
def get_forced_decision(context)
return nil if @optimizely_client&.get_optimizely_config.nil?

find_forced_decision(flag_key, rule_key)
find_forced_decision(context)
end

# Removes the forced decision for a given flag and an optional rule.
#
# @param flag_key - A flag key.
# @param rule_key - An experiment or delivery rule key (optional).
# @param context - An OptimizelyDecisionContext object containg flag key and rule key.
#
# @return - true if the forced decision has been removed successfully.

def remove_forced_decision(flag_key, rule_key = nil)
def remove_forced_decision(context)
return false if @optimizely_client&.get_optimizely_config.nil?

forced_decision_key = ForcedDecision.new(flag_key, rule_key)
deleted = false
@forced_decision_mutex.synchronize do
if @forced_decisions.key?(forced_decision_key)
@forced_decisions.delete(forced_decision_key)
if @forced_decisions.key?(context)
@forced_decisions.delete(context)
deleted = true
end
end
Expand All @@ -164,8 +161,11 @@ def remove_all_forced_decision
true
end

def find_validated_forced_decision(flag_key, rule_key)
variation_key = find_forced_decision(flag_key, rule_key)
def find_validated_forced_decision(context)
decision = find_forced_decision(context)
flag_key = context[:flag_key]
rule_key = context[:rule_key]
variation_key = decision ? decision[:variation_key] : decision
reasons = []
target = rule_key ? "flag (#{flag_key}), rule (#{rule_key})" : "flag (#{flag_key})"
if variation_key
Expand Down
Loading