Skip to content

Commit 435e595

Browse files
committed
Updated client
1 parent 16746c2 commit 435e595

File tree

8 files changed

+291
-73
lines changed

8 files changed

+291
-73
lines changed

lib/splitclient-rb/clients/split_client.rb

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class SplitClient
1818
# @param sdk_key [String] the SDK key for your split account
1919
#
2020
# @return [SplitIoClient] split.io client instance
21-
def initialize(sdk_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer, evaluator, split_validator)
21+
def initialize(sdk_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer, evaluator, split_validator, fallback_treatment_calculator)
2222
@api_key = sdk_key
2323
@splits_repository = repositories[:splits]
2424
@segments_repository = repositories[:segments]
@@ -32,6 +32,7 @@ def initialize(sdk_key, repositories, status_manager, config, impressions_manage
3232
@telemetry_evaluation_producer = telemetry_evaluation_producer
3333
@split_validator = split_validator
3434
@evaluator = evaluator
35+
@fallback_treatment_calculator = fallback_treatment_calculator
3536
end
3637

3738
def get_treatment(
@@ -277,7 +278,7 @@ def treatments(key, feature_flag_names, attributes = {}, evaluation_options = ni
277278
if !@config.split_validator.valid_get_treatments_parameters(calling_method, key, sanitized_feature_flag_names, matching_key, bucketing_key, attributes)
278279
to_return = Hash.new
279280
sanitized_feature_flag_names.each {|name|
280-
to_return[name.to_sym] = control_treatment_with_config
281+
to_return[name.to_sym] = check_fallback_treatment(name, '')
281282
}
282283
return to_return
283284
end
@@ -286,9 +287,11 @@ def treatments(key, feature_flag_names, attributes = {}, evaluation_options = ni
286287
impressions = []
287288
to_return = Hash.new
288289
sanitized_feature_flag_names.each {|name|
289-
to_return[name.to_sym] = control_treatment_with_config
290+
treatment_data = check_fallback_treatment(name, Engine::Models::Label::NOT_READY)
291+
to_return[name.to_sym] = treatment_data
292+
290293
impressions << { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, name.to_sym,
291-
control_treatment_with_config.merge({ :label => Engine::Models::Label::NOT_READY }), false, { attributes: attributes, time: nil },
294+
get_treatment_without_config(treatment_data), false, { attributes: attributes, time: nil },
292295
evaluation_options), :disabled => false }
293296
}
294297
@impressions_manager.track(impressions)
@@ -308,7 +311,7 @@ def treatments(key, feature_flag_names, attributes = {}, evaluation_options = ni
308311
if feature_flag.nil?
309312
@config.logger.warn("#{calling_method}: you passed #{key} that " \
310313
'does not exist in this environment, please double check what feature flags exist in the Split user interface')
311-
invalid_treatments[key] = control_treatment_with_config
314+
invalid_treatments[key] = check_fallback_treatment(key, Engine::Models::Label::NOT_FOUND)
312315
next
313316
end
314317
treatments_labels_change_numbers, impressions = evaluate_treatment(feature_flag, key, bucketing_key, matching_key, attributes, calling_method, false, evaluation_options)
@@ -344,7 +347,7 @@ def treatment(key, feature_flag_name, attributes = {}, split_data = nil, store_i
344347

345348
attributes = parsed_attributes(attributes)
346349

347-
return parsed_treatment(control_treatment, multiple) unless valid_client && @config.split_validator.valid_get_treatment_parameters(calling_method, key, feature_flag_name, matching_key, bucketing_key, attributes)
350+
return parsed_treatment(check_fallback_treatment(feature_flag_name, ""), multiple) unless valid_client && @config.split_validator.valid_get_treatment_parameters(calling_method, key, feature_flag_name, matching_key, bucketing_key, attributes)
348351

349352
bucketing_key = bucketing_key ? bucketing_key.to_s : nil
350353
matching_key = matching_key.to_s
@@ -373,7 +376,7 @@ def evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_
373376
if feature_flag.nil? && ready?
374377
@config.logger.warn("#{calling_method}: you passed #{feature_flag_name} that " \
375378
'does not exist in this environment, please double check what feature flags exist in the Split user interface')
376-
return parsed_treatment(control_treatment.merge({ :label => Engine::Models::Label::NOT_FOUND }), multiple), nil
379+
return check_fallback_treatment(feature_flag_name, Engine::Models::Label::NOT_FOUND), nil
377380
end
378381

379382
if !feature_flag.nil? && ready?
@@ -383,7 +386,7 @@ def evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_
383386
impressions_disabled = feature_flag[:impressionsDisabled]
384387
else
385388
@config.logger.error("#{calling_method}: the SDK is not ready, results may be incorrect for feature flag #{feature_flag_name}. Make sure to wait for SDK readiness before using this method.")
386-
treatment_data = control_treatment.merge({ :label => Engine::Models::Label::NOT_READY })
389+
treatment_data = check_fallback_treatment(feature_flag_name, Engine::Models::Label::NOT_READY)
387390
impressions_disabled = false
388391
end
389392

@@ -396,22 +399,16 @@ def evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_
396399
rescue StandardError => e
397400
@config.log_found_exception(__method__.to_s, e)
398401
record_exception(calling_method)
399-
impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, control_treatment, false, { attributes: attributes, time: nil }, evaluation_options), :disabled => false }
402+
treatment_data = check_fallback_treatment(feature_flag_name, Engine::Models::Label::EXCEPTION)
403+
impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, get_treatment_without_config(treatment_data), false, { attributes: attributes, time: nil }, evaluation_options), :disabled => false }
404+
400405
impressions_decorator << impression_decorator unless impression_decorator.nil?
401406

402-
return parsed_treatment(control_treatment.merge({ :label => Engine::Models::Label::EXCEPTION }), multiple), impressions_decorator
407+
return parsed_treatment(treatment_data, multiple), impressions_decorator
403408
end
404409
return parsed_treatment(treatment_data, multiple), impressions_decorator
405410
end
406411

407-
def control_treatment
408-
{ :treatment => Engine::Models::Treatment::CONTROL }
409-
end
410-
411-
def control_treatment_with_config
412-
{:treatment => Engine::Models::Treatment::CONTROL, :config => nil}
413-
end
414-
415412
def variable_size(value)
416413
value.is_a?(String) ? value.length : 0
417414
end
@@ -472,5 +469,31 @@ def record_exception(method)
472469
@telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TRACK)
473470
end
474471
end
472+
473+
def check_fallback_treatment(feature_name, label)
474+
fallback_treatment = @fallback_treatment_calculator.resolve(feature_name.to_sym, label)
475+
476+
{
477+
label: fallback_treatment.label,
478+
treatment: fallback_treatment.treatment,
479+
config: get_fallback_config(fallback_treatment)
480+
}
481+
end
482+
483+
def get_treatment_without_config(treatment)
484+
{
485+
label: treatment[:label],
486+
treatment: treatment[:treatment],
487+
}
488+
end
489+
490+
def get_fallback_config(fallback_treatment)
491+
if fallback_treatment.config != nil
492+
return fallback_treatment.config
493+
end
494+
495+
return nil
496+
end
497+
475498
end
476499
end

lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def build_global_fallback_treatment(global_fallback_treatment)
1818
end
1919

2020
def build_by_flag_fallback_treatment(by_flag_fallback_treatment)
21-
return nil unless by_flag_fallback_treatment.is_a? Hash
21+
return nil unless by_flag_fallback_treatment.is_a?(Hash)
2222
processed_by_flag_fallback_treatment = Hash.new
2323

2424
by_flag_fallback_treatment.each do |key, value|

lib/splitclient-rb/split_config.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -712,15 +712,16 @@ def self.sanitize_fallback_config(fallback_config, validator, logger)
712712
end
713713

714714
sanitized_global_fallback_treatment = fallback_config.global_fallback_treatment
715-
if !fallback_config.global_fallback_treatment.nil? && !validator.validate_fallback_treatment(fallback_config.global_fallback_treatment)
715+
if !fallback_config.global_fallback_treatment.nil? && !validator.validate_fallback_treatment('Config', fallback_config.global_fallback_treatment)
716716
logger.warn('Config: global fallbacktreatment parameter is discarded.')
717-
sanitized_global_fallback_treatment = None
717+
sanitized_global_fallback_treatment = nil
718718
end
719719

720-
sanitized_flag_fallback_treatments = Hash.new
720+
sanitized_flag_fallback_treatments = nil
721721
if !fallback_config.by_flag_fallback_treatment.nil? && fallback_config.by_flag_fallback_treatment.is_a?(Hash)
722+
sanitized_flag_fallback_treatments = Hash.new
722723
for feature_name in fallback_config.by_flag_fallback_treatment.keys()
723-
if !validator.valid_split_name?('Config', feature_name) || !validator.validate_fallback_treatment(fallback_config.by_flag_fallback_treatment[feature_name])
724+
if !validator.valid_split_name?('Config', feature_name) || !validator.validate_fallback_treatment('Config', fallback_config.by_flag_fallback_treatment[feature_name])
724725
logger.warn("Config: fallback treatment parameter for feature flag #{feature_name} is discarded.")
725726
next
726727
end

lib/splitclient-rb/split_factory.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ def initialize(api_key, config_hash = {})
5858
@evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @rule_based_segment_repository, @config)
5959

6060
start!
61-
62-
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator)
61+
62+
fallback_treatment_calculator = SplitIoClient::Engine::FallbackTreatmentCalculator.new(SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new)
63+
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator, fallback_treatment_calculator)
6364
@manager = SplitManager.new(@splits_repository, @status_manager, @config)
6465
end
6566

lib/splitclient-rb/validators.rb

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def valid_flag_sets(method, flag_sets)
7070
log_invalid_flag_set_type(method)
7171
elsif flag_set.is_a?(String) && flag_set.empty?
7272
log_invalid_flag_set_type(method)
73-
elsif !flag_set.empty? && string_match?(flag_set.strip.downcase, method, Flagset_regex, log_invalid_match)
73+
elsif !flag_set.empty? && string_match?(flag_set.strip.downcase, method, Flagset_regex, :log_invalid_match)
7474
valid_flag_sets.add(flag_set.strip.downcase)
7575
else
7676
log_invalid_flag_set_type(method)
@@ -79,6 +79,46 @@ def valid_flag_sets(method, flag_sets)
7979
!valid_flag_sets.empty? ? valid_flag_sets.to_a.sort : []
8080
end
8181

82+
def validate_fallback_treatment(method, fallback_treatment)
83+
if !fallback_treatment.is_a? Engine::Models::FallbackTreatment
84+
@config.logger.warn("#{method}: Fallback treatment instance should be FallbackTreatment, input is discarded")
85+
return false
86+
end
87+
88+
if !fallback_treatment.treatment.is_a? String
89+
@config.logger.warn("#{method}: Fallback treatment value should be str type, input is discarded")
90+
return false
91+
end
92+
93+
return false unless string_match?(fallback_treatment.treatment, method, Fallback_treatment_regex, :log_invalid_fallback_treatment)
94+
95+
if fallback_treatment.treatment.size > Fallback_treatment_size
96+
@config.logger.warn("#{method}: Fallback treatment size should not exceed #{Fallback_treatment_size} characters")
97+
return false
98+
end
99+
100+
true
101+
end
102+
103+
def valid_split_name?(method, split_name)
104+
if split_name.nil?
105+
log_nil(:split_name, method)
106+
return false
107+
end
108+
109+
unless string?(split_name)
110+
log_invalid_type(:split_name, method)
111+
return false
112+
end
113+
114+
if empty_string?(split_name)
115+
log_empty_string(:split_name, method)
116+
return false
117+
end
118+
119+
true
120+
end
121+
82122
private
83123

84124
def string?(value)
@@ -95,7 +135,7 @@ def number_or_string?(value)
95135

96136
def string_match?(value, method, regex_exp, log_if_invalid)
97137
if regex_exp.match(value) == nil
98-
log_if_invalid(value, method)
138+
method(log_if_invalid).call(value, method)
99139
false
100140
else
101141
true
@@ -134,25 +174,6 @@ def log_key_too_long(key, method)
134174
@config.logger.error("#{method}: #{key} is too long - must be #{@config.max_key_size} characters or less")
135175
end
136176

137-
def valid_split_name?(method, split_name)
138-
if split_name.nil?
139-
log_nil(:split_name, method)
140-
return false
141-
end
142-
143-
unless string?(split_name)
144-
log_invalid_type(:split_name, method)
145-
return false
146-
end
147-
148-
if empty_string?(split_name)
149-
log_empty_string(:split_name, method)
150-
return false
151-
end
152-
153-
true
154-
end
155-
156177
def valid_key?(method, key)
157178
if key.nil?
158179
log_nil(:key, method)
@@ -329,29 +350,8 @@ def valid_properties?(properties)
329350
true
330351
end
331352

332-
def validate_fallback_treatment(method, fallback_treatment)
333-
if !fallback_treatment.is_a? Engine::Models::FallbackTreatment
334-
@config.logger.warn("#{method}: Fallback treatment instance should be FallbackTreatment, input is discarded")
335-
return false
336-
end
337-
338-
if !fallback_treatment.treatment.is_a? String
339-
@config.logger.warn("#{method}: Fallback treatment value should be str type, input is discarded")
340-
return false
341-
end
342-
343-
return false unless string_match?(fallback_treatment.treatment, method, Fallback_treatment_regex)
344-
345-
if fallback_treatment.treatment.size > Fallback_treatment_size
346-
@config.logger.warn("#{method}: Fallback treatment size should not exceed %s characters", Fallback_treatment_size)
347-
return false
348-
end
349-
350-
true
351-
end
352-
353353
def log_invalid_fallback_treatment(key, method)
354-
@config.logger.warn("#{method}: Invalid treatment #{key}, Fallback treatment should match regex %s", Fallback_treatment_regex)
354+
@config.logger.warn("#{method}: Invalid treatment #{key}, Fallback treatment should match regex #{Fallback_treatment_regex}")
355355
end
356356
end
357357
end

0 commit comments

Comments
 (0)