-
Notifications
You must be signed in to change notification settings - Fork 27
feat(Decide): Add Decide API #274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
4f8765b
a7b78d8
c5f138c
c8d3a35
f770ce7
244c4f3
1bd6df7
ddd5349
98ced8c
e7366f4
03a397f
3e9e417
ab824c7
507dac6
13833de
b981f64
d102a14
7fb2ddf
16a509d
f6437b7
ac90cd0
4026855
d6be7c2
752114d
ee32ee1
57ac8a0
a300b3e
0070d3b
6727d30
d9a5549
cd1648e
8ec1619
a041cb6
7d122a4
c40237f
7f6d985
b793012
0a38bdd
c401588
cffa963
43b14ee
245637e
b76af55
5057b3f
92afe26
1ef9539
89c3d6b
315d4aa
f58d8bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -156,7 +156,7 @@ def decide(user_context, key, decide_options = []) | |
| # validate that key is a string | ||
| unless key.is_a?(String) | ||
| @logger.log(Logger::ERROR, 'Provided key is invalid') | ||
| reasons.push(OptimizelyDecisionMessage::VARIABLE_VALUE_INVALID) | ||
| reasons.push(format(OptimizelyDecisionMessage::FLAG_KEY_INVALID, key)) | ||
| return OptimizelyDecision.new(flag_key: key, user_context: user_context, reasons: reasons) | ||
| end | ||
|
|
||
|
|
@@ -187,7 +187,7 @@ def decide(user_context, key, decide_options = []) | |
| all_variables = {} | ||
| decision_event_dispatched = false | ||
|
|
||
| decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes, decide_options) | ||
| decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes, decide_options, reasons) | ||
|
|
||
| # Send impression event if Decision came from a feature test and decide options doesn't include disableDecisionEvent | ||
| if decision.is_a?(Optimizely::DecisionService::Decision) | ||
|
|
@@ -197,19 +197,22 @@ def decide(user_context, key, decide_options = []) | |
| flag_key = key | ||
| rule_key = decision.experiment['key'] | ||
|
|
||
| if decision.source == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST'] | ||
| unless decide_options.include? Optimizely::Decide::OptimizelyDecideOption::DISABLE_DECISION_EVENT | ||
| source_string = Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST'] | ||
| send_impression( | ||
| config, decision.experiment, variation_key, flag_key, rule_key, source_string, user_id, attributes | ||
| ) | ||
| unless decide_options.include? OptimizelyDecideOption::DISABLE_DECISION_EVENT | ||
| if decision.source == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST'] || | ||
| (decision.source == Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT'] && config.send_flag_decisions) | ||
| send_impression(config, decision.experiment, variation_key, flag_key, rule_key, decision.source, user_id, attributes) | ||
| decision_event_dispatched = true | ||
| end | ||
| end | ||
| end | ||
|
|
||
| if decision.nil? && config.send_flag_decisions | ||
| send_impression(config, nil, '', flag_key, '', Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT'], user_id, attributes) | ||
| decision_event_dispatched = true | ||
| end | ||
|
||
|
|
||
| # Generate all variables map if decide options doesn't include excludeVariables | ||
| unless decide_options.include? Optimizely::Decide::OptimizelyDecideOption::EXCLUDE_VARIABLES | ||
| unless decide_options.include? OptimizelyDecideOption::EXCLUDE_VARIABLES | ||
| feature_flag['variables'].each do |variable| | ||
| variable_value = get_feature_variable_for_variation(key, feature_enabled, variation, variable, user_id) | ||
| all_variables[variable['key']] = Helpers::VariableType.cast_value_to_type(variable_value, variable['type'], @logger) | ||
|
|
@@ -230,24 +233,50 @@ def decide(user_context, key, decide_options = []) | |
| decision_event_dispatched: decision_event_dispatched | ||
| ) | ||
|
|
||
| should_include_reasons = decide_options.include? OptimizelyDecideOption::INCLUDE_REASONS | ||
| OptimizelyDecision.new( | ||
| variation_key: variation_key, | ||
| enabled: feature_enabled, | ||
| variables: all_variables, | ||
| rule_key: rule_key, | ||
| flag_key: flag_key, | ||
| user_context: user_context, | ||
| reasons: reasons | ||
| reasons: should_include_reasons ? reasons : [] | ||
| ) | ||
| end | ||
|
|
||
| def decide_all(user_context, decide_options = []) | ||
| # raising on user context as it is internal and not provided directly by the user. | ||
| raise if user_context.class != OptimizelyUserContext | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add checking SDK_NOT_READY error here? If not, we should return an empty map instead of a map of error-decisions.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| decisions = {} | ||
| # check if SDK is ready | ||
| unless is_valid | ||
| @logger.log(Logger::ERROR, InvalidProjectConfigError.new('decide_all').message) | ||
| return {} | ||
| end | ||
|
|
||
| keys = [] | ||
| project_config.feature_flags.each do |feature_flag| | ||
| decisions[feature_flag['key']] = decide(user_context, feature_flag['key'], decide_options) | ||
| keys.push(feature_flag['key']) | ||
| end | ||
| decide_for_keys(user_context, keys, decide_options) | ||
| end | ||
|
|
||
| def decide_for_keys(user_context, keys, decide_options = []) | ||
| # raising on user context as it is internal and not provided directly by the user. | ||
| raise if user_context.class != OptimizelyUserContext | ||
|
|
||
| # check if SDK is ready | ||
| unless is_valid | ||
| @logger.log(Logger::ERROR, InvalidProjectConfigError.new('decide_for_keys').message) | ||
| return {} | ||
| end | ||
|
|
||
| enabled_flags_only = !decide_options.nil? && (decide_options.include? OptimizelyDecideOption::ENABLED_FLAGS_ONLY) | ||
|
||
| decisions = {} | ||
| keys.each do |key| | ||
| decision = decide(user_context, key, decide_options) | ||
| decisions[key] = decision unless enabled_flags_only && !decision.enabled | ||
| end | ||
| decisions | ||
| end | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When rule-key is not available, it's ok to set it to experiment key (pre-velociraptor). Ideally, we can add "rule_key" into Decision for velociraptor support as well.