Skip to content

Commit 4bc21d5

Browse files
committed
Update client
1 parent e18d900 commit 4bc21d5

File tree

4 files changed

+79
-34
lines changed

4 files changed

+79
-34
lines changed

lib/splitclient-rb/clients/split_client.rb

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,64 +35,64 @@ def initialize(sdk_key, repositories, status_manager, config, impressions_manage
3535
end
3636

3737
def get_treatment(
38-
key, split_name, attributes = {}, split_data = nil, store_impressions = true,
38+
key, split_name, attributes = {}, options = nil, split_data = nil, store_impressions = true,
3939
multiple = false, evaluator = nil
4040
)
41-
result = treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT, multiple)
41+
result = treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT, multiple, options)
4242
return result.tap { |t| t.delete(:config) } if multiple
4343
result[:treatment]
4444
end
4545

4646
def get_treatment_with_config(
47-
key, split_name, attributes = {}, split_data = nil, store_impressions = true,
47+
key, split_name, attributes = {}, options = nil, split_data = nil, store_impressions = true,
4848
multiple = false, evaluator = nil
4949
)
50-
treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT_WITH_CONFIG, multiple)
50+
treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT_WITH_CONFIG, multiple, options)
5151
end
5252

53-
def get_treatments(key, split_names, attributes = {})
54-
treatments = treatments(key, split_names, attributes)
53+
def get_treatments(key, split_names, attributes = {}, options = nil)
54+
treatments = treatments(key, split_names, attributes, options)
5555

5656
return treatments if treatments.nil?
5757
keys = treatments.keys
5858
treats = treatments.map { |_,t| t[:treatment] }
5959
Hash[keys.zip(treats)]
6060
end
6161

62-
def get_treatments_with_config(key, split_names, attributes = {})
63-
treatments(key, split_names, attributes, GET_TREATMENTS_WITH_CONFIG)
62+
def get_treatments_with_config(key, split_names, attributes = {}, options = nil)
63+
treatments(key, split_names, attributes, options, GET_TREATMENTS_WITH_CONFIG)
6464
end
6565

66-
def get_treatments_by_flag_set(key, flag_set, attributes = {})
66+
def get_treatments_by_flag_set(key, flag_set, attributes = {}, options = nil)
6767
valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_BY_FLAG_SET, [flag_set])
6868
split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
69-
treatments = treatments(key, split_names, attributes, GET_TREATMENTS_BY_FLAG_SET)
69+
treatments = treatments(key, split_names, attributes, options, GET_TREATMENTS_BY_FLAG_SET)
7070
return treatments if treatments.nil?
7171
keys = treatments.keys
7272
treats = treatments.map { |_,t| t[:treatment] }
7373
Hash[keys.zip(treats)]
7474
end
7575

76-
def get_treatments_by_flag_sets(key, flag_sets, attributes = {})
76+
def get_treatments_by_flag_sets(key, flag_sets, attributes = {}, options = nil)
7777
valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_BY_FLAG_SETS, flag_sets)
7878
split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
79-
treatments = treatments(key, split_names, attributes, GET_TREATMENTS_BY_FLAG_SETS)
79+
treatments = treatments(key, split_names, attributes, options, GET_TREATMENTS_BY_FLAG_SETS)
8080
return treatments if treatments.nil?
8181
keys = treatments.keys
8282
treats = treatments.map { |_,t| t[:treatment] }
8383
Hash[keys.zip(treats)]
8484
end
8585

86-
def get_treatments_with_config_by_flag_set(key, flag_set, attributes = {})
86+
def get_treatments_with_config_by_flag_set(key, flag_set, attributes = {}, options = nil)
8787
valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, [flag_set])
8888
split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
89-
treatments(key, split_names, attributes, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET)
89+
treatments(key, split_names, attributes, options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET)
9090
end
9191

92-
def get_treatments_with_config_by_flag_sets(key, flag_sets, attributes = {})
92+
def get_treatments_with_config_by_flag_sets(key, flag_sets, attributes = {}, options = nil)
9393
valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, flag_sets)
9494
split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
95-
treatments(key, split_names, attributes, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS)
95+
treatments(key, split_names, attributes, options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS)
9696
end
9797

9898
def destroy
@@ -135,10 +135,7 @@ def track(key, traffic_type_name, event_type, value = nil, properties = nil)
135135
if !properties.nil?
136136
properties, size = validate_properties(properties)
137137
properties_size += size
138-
if (properties_size > EVENTS_SIZE_THRESHOLD)
139-
@config.logger.error("The maximum size allowed for the properties is #{EVENTS_SIZE_THRESHOLD}. Current is #{properties_size}. Event not queued")
140-
return false
141-
end
138+
return false unless check_properties_size(properties_size)
142139
end
143140

144141
if ready? && !@config.localhost_mode && !@splits_repository.traffic_type_exists(traffic_type_name)
@@ -163,6 +160,14 @@ def block_until_ready(time = nil)
163160

164161
private
165162

163+
def check_properties_size(properties_size, msg = "Event not queued")
164+
if (properties_size > EVENTS_SIZE_THRESHOLD)
165+
@config.logger.error("The maximum size allowed for the properties is #{EVENTS_SIZE_THRESHOLD}. Current is #{properties_size}. #{msg}")
166+
return false
167+
end
168+
return true
169+
end
170+
166171
def keys_from_key(key)
167172
case key
168173
when Hash
@@ -206,7 +211,7 @@ def sanitize_split_names(calling_method, split_names)
206211
end
207212
end
208213

209-
def validate_properties(properties)
214+
def validate_properties(properties, method = 'Event')
210215
properties_count = 0
211216
size = 0
212217

@@ -225,11 +230,25 @@ def validate_properties(properties)
225230
end
226231
}
227232

228-
@config.logger.warn('Event has more than 300 properties. Some of them will be trimmed when processed') if properties_count > 300
233+
@config.logger.warn("#{method} has more than 300 properties. Some of them will be trimmed when processed") if properties_count > 300
229234

230235
return fixed_properties, size
231236
end
232237

238+
def validate_options(options)
239+
if !options.is_a?(Hash)
240+
@config.logger.warn("Option #{options} should be a hash type. Setting value to nil")
241+
return nil, 0
242+
end
243+
options = options.transform_keys(&:to_sym)
244+
if !options.key?(:properties)
245+
@config.logger.warn("Option #{options} hash does not contain properties key. Setting value to nil")
246+
return nil, 0
247+
end
248+
options[:properties], size = validate_properties(options[:properties], method = 'Treatment')
249+
return options, size
250+
end
251+
233252
def valid_client
234253
if @destroyed
235254
@config.logger.error('Client has already been destroyed - no calls possible')
@@ -238,8 +257,7 @@ def valid_client
238257
@config.valid_mode
239258
end
240259

241-
def treatments(key, feature_flag_names, attributes = {}, calling_method = 'get_treatments')
242-
attributes = {} if attributes.nil?
260+
def treatments(key, feature_flag_names, attributes = {}, options = nil, calling_method = 'get_treatments')
243261
sanitized_feature_flag_names = sanitize_split_names(calling_method, feature_flag_names)
244262

245263
if sanitized_feature_flag_names.nil?
@@ -269,7 +287,9 @@ def treatments(key, feature_flag_names, attributes = {}, calling_method = 'get_t
269287
to_return = Hash.new
270288
sanitized_feature_flag_names.each {|name|
271289
to_return[name.to_sym] = control_treatment_with_config
272-
impressions << { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, name.to_sym, control_treatment_with_config.merge({ :label => Engine::Models::Label::NOT_READY }), false, { attributes: attributes, time: nil }), :disabled => false }
290+
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 },
292+
options), :disabled => false }
273293
}
274294
@impressions_manager.track(impressions)
275295
return to_return
@@ -291,7 +311,7 @@ def treatments(key, feature_flag_names, attributes = {}, calling_method = 'get_t
291311
invalid_treatments[key] = control_treatment_with_config
292312
next
293313
end
294-
treatments_labels_change_numbers, impressions = evaluate_treatment(feature_flag, key, bucketing_key, matching_key, attributes, calling_method)
314+
treatments_labels_change_numbers, impressions = evaluate_treatment(feature_flag, key, bucketing_key, matching_key, attributes, calling_method, false, options)
295315
treatments[key] =
296316
{
297317
treatment: treatments_labels_change_numbers[:treatment],
@@ -314,7 +334,7 @@ def treatments(key, feature_flag_names, attributes = {}, calling_method = 'get_t
314334
# @param store_impressions [Boolean] impressions aren't stored if this flag is false
315335
# @return [String/Hash] Treatment as String or Hash of treatments in case of array of features
316336
def treatment(key, feature_flag_name, attributes = {}, split_data = nil, store_impressions = true,
317-
calling_method = 'get_treatment', multiple = false)
337+
calling_method = 'get_treatment', multiple = false, options = nil)
318338
impressions = []
319339
bucketing_key, matching_key = keys_from_key(key)
320340

@@ -332,13 +352,13 @@ def treatment(key, feature_flag_name, attributes = {}, split_data = nil, store_i
332352
end
333353

334354
feature_flag = @splits_repository.get_split(feature_flag_name)
335-
treatments, impressions_decorator = evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_key, attributes, calling_method, multiple)
355+
treatments, impressions_decorator = evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_key, attributes, calling_method, multiple, options)
336356

337357
@impressions_manager.track(impressions_decorator) unless impressions_decorator.nil?
338358
treatments
339359
end
340360

341-
def evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_key, attributes, calling_method, multiple = false)
361+
def evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_key, attributes, calling_method, multiple = false, options = nil)
342362
impressions_decorator = []
343363
begin
344364
start = Time.now
@@ -359,18 +379,20 @@ def evaluate_treatment(feature_flag, feature_flag_name, bucketing_key, matching_
359379
impressions_disabled = false
360380
end
361381

382+
options, size = validate_options(options)
383+
options[:properties] = nil unless options.nil? or check_properties_size((EVENT_AVERAGE_SIZE + size), "Properties are ignored")
384+
362385
record_latency(calling_method, start)
363-
impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, treatment_data, impressions_disabled, { attributes: attributes, time: nil }), :disabled => impressions_disabled }
386+
impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, treatment_data, impressions_disabled, { attributes: attributes, time: nil }, options), :disabled => impressions_disabled }
364387
impressions_decorator << impression_decorator unless impression_decorator.nil?
365388
rescue StandardError => e
366389
@config.log_found_exception(__method__.to_s, e)
367390
record_exception(calling_method)
368-
impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, control_treatment, false, { attributes: attributes, time: nil }), :disabled => false }
391+
impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, control_treatment, false, { attributes: attributes, time: nil }, options), :disabled => false }
369392
impressions_decorator << impression_decorator unless impression_decorator.nil?
370393

371394
return parsed_treatment(control_treatment.merge({ :label => Engine::Models::Label::EXCEPTION }), multiple), impressions_decorator
372395
end
373-
374396
return parsed_treatment(treatment_data, multiple), impressions_decorator
375397
end
376398

lib/splitclient-rb/engine/common/impressions_manager.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ def initialize(config,
1919
end
2020

2121
def build_impression(matching_key, bucketing_key, split_name, treatment_data, impressions_disabled, params = {},
22-
properties = nil)
22+
options = nil)
23+
properties = options.nil? ? nil : options[:properties]
2324
impression_data = impression_data(matching_key, bucketing_key, split_name, treatment_data, params[:time], properties)
2425
begin
2526
if @config.impressions_mode == :none || impressions_disabled

spec/engine/common/impression_manager_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
'split_name_test',
7373
treatment,
7474
false,
75-
params, {"prop":"val"})
75+
params, {"properties": {"prop":"val"}})
7676
expect(impression).to match(expected)
7777

7878
result_count = impression_counter.pop_all

spec/splitclient/split_client_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@
3535
expect(split_client.get_treatments_by_flag_sets('key', ['set_2'])).to eq({:testing222 => 'off'})
3636
expect(split_client.get_treatments_with_config_by_flag_set('key', 'set_1')).to eq({:testing222 => {:treatment => 'off', :config => nil}})
3737
expect(split_client.get_treatments_with_config_by_flag_sets('key', ['set_2'])).to eq({:testing222 => {:treatment => 'off', :config => nil}})
38+
imps = impressions_repository.batch
39+
40+
expect(split_client.get_treatment('key', 'testing222', {}, {:properties => {:prop => "value"}})).to eq('off')
41+
check_properties(impressions_repository.batch)
42+
expect(split_client.get_treatments('key_prop', ['testing222'], {}, {:properties => {:prop => "value"}})).to eq({:testing222 => 'off'})
43+
check_properties(impressions_repository.batch)
44+
expect(split_client.get_treatment_with_config('key', 'testing222', {}, {:properties => {:prop => "value"}})).to eq({:treatment => 'off', :config => nil})
45+
check_properties(impressions_repository.batch)
46+
expect(split_client.get_treatments_with_config('key', ['testing222'], {}, {:properties => {:prop => "value"}})).to eq({:testing222 => {:treatment => 'off', :config => nil}})
47+
check_properties(impressions_repository.batch)
48+
expect(split_client.get_treatments_by_flag_set('key', 'set_1', {}, {:properties => {:prop => "value"}})).to eq({:testing222 => 'off'})
49+
check_properties(impressions_repository.batch)
50+
expect(split_client.get_treatments_by_flag_sets('key', ['set_2'], {}, {:properties => {:prop => "value"}})).to eq({:testing222 => 'off'})
51+
check_properties(impressions_repository.batch)
52+
expect(split_client.get_treatments_with_config_by_flag_set('key', 'set_1', {}, {:properties => {:prop => "value"}})).to eq({:testing222 => {:treatment => 'off', :config => nil}})
53+
check_properties(impressions_repository.batch)
54+
expect(split_client.get_treatments_with_config_by_flag_sets('key', ['set_2'], {}, {:properties => {:prop => "value"}})).to eq({:testing222 => {:treatment => 'off', :config => nil}})
55+
check_properties(impressions_repository.batch)
3856
end
3957

4058
it 'check track' do
@@ -221,3 +239,7 @@ def mock_segment_changes(segment_name, segment_json, since)
221239
stub_request(:get, "https://sdk.split.io/api/segmentChanges/#{segment_name}?since=#{since}")
222240
.to_return(status: 200, body: segment_json)
223241
end
242+
243+
def check_properties(imps)
244+
expect(imps[0][:i][:properties]).to eq({:prop => "value"})
245+
end

0 commit comments

Comments
 (0)