Skip to content

Commit 594d33e

Browse files
committed
Updated client, factory and integration tests
1 parent 2d9bbf8 commit 594d33e

File tree

6 files changed

+262
-9
lines changed

6 files changed

+262
-9
lines changed

lib/splitclient-rb/clients/split_client.rb

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ def get_treatment_with_config(
5151
multiple = false, evaluator = nil
5252
)
5353
log_deprecated_warning(GET_TREATMENT, evaluator, 'evaluator')
54-
treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT_WITH_CONFIG, multiple, evaluation_options)
54+
result = treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT_WITH_CONFIG, multiple, evaluation_options)
55+
56+
{ :config => result[:config], :treatment => result[:treatment] }
5557
end
5658

5759
def get_treatments(key, split_names, attributes = {}, evaluation_options = nil)
@@ -64,7 +66,11 @@ def get_treatments(key, split_names, attributes = {}, evaluation_options = nil)
6466
end
6567

6668
def get_treatments_with_config(key, split_names, attributes = {}, evaluation_options = nil)
67-
treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG)
69+
results = treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG)
70+
71+
results.map{|key, value|
72+
[key, { treatment: value[:treatment], config: value[:config] }]
73+
}.to_h
6874
end
6975

7076
def get_treatments_by_flag_set(key, flag_set, attributes = {}, evaluation_options = nil)
@@ -90,13 +96,21 @@ def get_treatments_by_flag_sets(key, flag_sets, attributes = {}, evaluation_opti
9096
def get_treatments_with_config_by_flag_set(key, flag_set, attributes = {}, evaluation_options = nil)
9197
valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, [flag_set])
9298
split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
93-
treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET)
99+
results = treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET)
100+
101+
results.map{|key, value|
102+
[key, { treatment: value[:treatment], config: value[:config] }]
103+
}.to_h
94104
end
95105

96106
def get_treatments_with_config_by_flag_sets(key, flag_sets, attributes = {}, evaluation_options = nil)
97107
valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, flag_sets)
98108
split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
99-
treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS)
109+
results = treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS)
110+
111+
results.map{|key, value|
112+
[key, { treatment: value[:treatment], config: value[:config] }]
113+
}.to_h
100114
end
101115

102116
def destroy
@@ -471,12 +485,20 @@ def record_exception(method)
471485
end
472486

473487
def check_fallback_treatment(feature_name, label)
488+
return {
489+
label: (label != '')? label : nil,
490+
treatment: Engine::Models::Treatment::CONTROL,
491+
config: nil,
492+
change_number: nil
493+
} unless feature_name.is_a?(Symbol) || feature_name.is_a?(String)
494+
474495
fallback_treatment = @fallback_treatment_calculator.resolve(feature_name.to_sym, label)
475496

476497
{
477-
label: fallback_treatment.label,
498+
label: (label != '')? fallback_treatment.label : nil,
478499
treatment: fallback_treatment.treatment,
479-
config: get_fallback_config(fallback_treatment)
500+
config: get_fallback_config(fallback_treatment),
501+
change_number: nil
480502
}
481503
end
482504

lib/splitclient-rb/split_factory.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ 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-
fallback_treatment_calculator = SplitIoClient::Engine::FallbackTreatmentCalculator.new(SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new)
61+
fallback_treatment_calculator = SplitIoClient::Engine::FallbackTreatmentCalculator.new(@config.fallback_treatments_configuration)
6362
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator, fallback_treatment_calculator)
6463
@manager = SplitManager.new(@splits_repository, @status_manager, @config)
6564
end

spec/allocations/splitclient-rb/clients/split_client_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
let(:telemetry_api) { SplitIoClient::Api::TelemetryApi.new(config, api_key, runtime_producer) }
2222
let(:impressions_api) { SplitIoClient::Api::Impressions.new(api_key, config, runtime_producer) }
2323
let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, rule_based_segments_repository, config) }
24+
let(:fallback_treatment_calculator) { SplitIoClient::Engine::FallbackTreatmentCalculator.new(SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new) }
2425
let(:sender_adapter) do
2526
SplitIoClient::Cache::Senders::ImpressionsSenderAdapter.new(config,
2627
telemetry_api,
@@ -41,7 +42,7 @@
4142
unique_keys_tracker)
4243
end
4344
let(:client) do
44-
SplitIoClient::SplitClient.new('', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => nil}, nil, config, impressions_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config))
45+
SplitIoClient::SplitClient.new('', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => nil}, nil, config, impressions_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config), fallback_treatment_calculator)
4546
end
4647

4748
context 'control' do

spec/integrations/in_memory_client_spec.rb

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,122 @@
14431443
expect(client_old_spec.get_treatment('whitelisted_user', 'whitelist_feature')).to eq('control')
14441444
end
14451445
end
1446+
1447+
context 'fallback treatments' do
1448+
it 'feature not found' do
1449+
splits_fallback = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json'))
1450+
stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')
1451+
.to_return(status: 200, body: splits_fallback)
1452+
factory_fallback =
1453+
SplitIoClient::SplitFactory.new('test_api_key',
1454+
fallback_treatments: SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new(
1455+
SplitIoClient::Engine::Models::FallbackTreatment.new(
1456+
"on-global", '{"prop": "global"}'
1457+
),
1458+
{:feature => SplitIoClient::Engine::Models::FallbackTreatment.new(
1459+
"on-local", '{"prop": "local"}'
1460+
)
1461+
}
1462+
),
1463+
impressions_mode: :optimized,
1464+
features_refresh_rate: 9999,
1465+
telemetry_refresh_rate: 99999,
1466+
impressions_refresh_rate: 99999,
1467+
streaming_enabled: false
1468+
)
1469+
1470+
client_fallback = factory_fallback.client
1471+
client_fallback.block_until_ready
1472+
result = client_fallback.get_treatment_with_config('key2', 'feature')
1473+
expect(result[:treatment]).to eq('on-local')
1474+
expect(result[:config]).to eq('{"prop": "local"}')
1475+
1476+
result = client_fallback.get_treatment_with_config('key3', 'feature2')
1477+
expect(result[:treatment]).to eq('on-global')
1478+
expect(result[:config]).to eq('{"prop": "global"}')
1479+
1480+
impressions_repository = client_fallback.instance_variable_get(:@impressions_repository)
1481+
imps = impressions_repository.batch
1482+
expect(imps.length()).to eq(0)
1483+
end
1484+
1485+
it 'exception' do
1486+
splits_fallback = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json'))
1487+
stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')
1488+
.to_return(status: 200, body: splits_fallback)
1489+
factory_fallback =
1490+
SplitIoClient::SplitFactory.new('test_api_key',
1491+
fallback_treatments: SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new(
1492+
SplitIoClient::Engine::Models::FallbackTreatment.new(
1493+
"on-global", '{"prop": "global"}'
1494+
),
1495+
{:feature => SplitIoClient::Engine::Models::FallbackTreatment.new(
1496+
"on-local", '{"prop": "local"}'
1497+
)
1498+
}
1499+
),
1500+
impressions_mode: :optimized,
1501+
features_refresh_rate: 9999,
1502+
telemetry_refresh_rate: 99999,
1503+
impressions_refresh_rate: 99999,
1504+
streaming_enabled: false
1505+
)
1506+
1507+
client_fallback = factory_fallback.client
1508+
client_fallback.block_until_ready
1509+
1510+
splits_repository = client_fallback.instance_variable_get(:@splits_repository)
1511+
splits = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json'))
1512+
split = JSON.parse(splits,:symbolize_names => true)[:ff][:d][0]
1513+
split[:trafficAllocation] = nil
1514+
splits_repository.update([split], [], -1)
1515+
1516+
result = client_fallback.get_treatment_with_config('key3', 'with_track_disabled')
1517+
expect(result[:treatment]).to eq('on-global')
1518+
expect(result[:config]).to eq('{"prop": "global"}')
1519+
1520+
impressions_repository = client_fallback.instance_variable_get(:@impressions_repository)
1521+
imps = impressions_repository.batch
1522+
expect(imps.length()).to eq(1)
1523+
expect(imps[0][:i][:f]).to eq('with_track_disabled')
1524+
expect(imps[0][:i][:r]).to eq('fallback - exception')
1525+
end
1526+
1527+
it 'client not ready' do
1528+
splits_fallback = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json'))
1529+
stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')
1530+
.to_return(status: 200, body: splits_fallback)
1531+
factory_fallback =
1532+
SplitIoClient::SplitFactory.new('test_api_key',
1533+
fallback_treatments: SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new(
1534+
SplitIoClient::Engine::Models::FallbackTreatment.new(
1535+
"on-global", '{"prop": "global"}'
1536+
),
1537+
{:feature => SplitIoClient::Engine::Models::FallbackTreatment.new(
1538+
"on-local", '{"prop": "local"}'
1539+
)
1540+
}
1541+
),
1542+
impressions_mode: :optimized,
1543+
features_refresh_rate: 9999,
1544+
telemetry_refresh_rate: 99999,
1545+
impressions_refresh_rate: 99999,
1546+
streaming_enabled: false
1547+
)
1548+
1549+
client_fallback = factory_fallback.client
1550+
1551+
result = client_fallback.get_treatment_with_config('key3', 'with_track_disabled')
1552+
expect(result[:treatment]).to eq('on-global')
1553+
expect(result[:config]).to eq('{"prop": "global"}')
1554+
1555+
impressions_repository = client_fallback.instance_variable_get(:@impressions_repository)
1556+
imps = impressions_repository.batch
1557+
expect(imps.length()).to eq(1)
1558+
expect(imps[0][:i][:f]).to eq('with_track_disabled')
1559+
expect(imps[0][:i][:r]).to eq('fallback - not ready')
1560+
end
1561+
end
14461562
end
14471563

14481564
private

spec/integrations/redis_client_spec.rb

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,94 @@
992992
expect(events.size).to eq 0
993993
end
994994
end
995+
996+
context 'fallback treatments' do
997+
it 'feature not found' do
998+
factory_fallback =
999+
SplitIoClient::SplitFactory.new('test_api_key',
1000+
fallback_treatments: SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new(
1001+
SplitIoClient::Engine::Models::FallbackTreatment.new(
1002+
"on-global", '{"prop": "global"}'
1003+
),
1004+
{:feature => SplitIoClient::Engine::Models::FallbackTreatment.new(
1005+
"on-local", '{"prop": "local"}'
1006+
)
1007+
}
1008+
),
1009+
logger: Logger.new(log),
1010+
cache_adapter: :redis,
1011+
redis_namespace: 'test',
1012+
mode: :consumer,
1013+
redis_url: 'redis://127.0.0.1:6379/0',
1014+
impression_listener: custom_impression_listener
1015+
)
1016+
1017+
client_fallback = factory_fallback.client
1018+
load_splits_redis(splits, client_fallback)
1019+
load_segment_redis(segment1, client_fallback)
1020+
load_segment_redis(segment2, client_fallback)
1021+
load_segment_redis(segment3, client_fallback)
1022+
load_flag_sets_redis(flag_sets, client_fallback)
1023+
client_fallback.block_until_ready
1024+
1025+
result = client_fallback.get_treatment_with_config('key2', 'feature')
1026+
expect(result[:treatment]).to eq('on-local')
1027+
expect(result[:config]).to eq('{"prop": "local"}')
1028+
1029+
result = client_fallback.get_treatment_with_config('key3', 'feature2')
1030+
expect(result[:treatment]).to eq('on-global')
1031+
expect(result[:config]).to eq('{"prop": "global"}')
1032+
1033+
sleep 0.5
1034+
impressions = custom_impression_listener.queue
1035+
expect(impressions.size).to eq 0
1036+
end
1037+
1038+
it 'exception' do
1039+
factory_fallback =
1040+
SplitIoClient::SplitFactory.new('test_api_key',
1041+
fallback_treatments: SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new(
1042+
SplitIoClient::Engine::Models::FallbackTreatment.new(
1043+
"on-global", '{"prop": "global"}'
1044+
),
1045+
{:feature => SplitIoClient::Engine::Models::FallbackTreatment.new(
1046+
"on-local", '{"prop": "local"}'
1047+
)
1048+
}
1049+
),
1050+
logger: Logger.new(log),
1051+
cache_adapter: :redis,
1052+
redis_namespace: 'test',
1053+
mode: :consumer,
1054+
redis_url: 'redis://127.0.0.1:6379/0',
1055+
impression_listener: custom_impression_listener
1056+
)
1057+
1058+
client_fallback = factory_fallback.client
1059+
load_splits_redis(splits, client_fallback)
1060+
load_segment_redis(segment1, client_fallback)
1061+
load_segment_redis(segment2, client_fallback)
1062+
load_segment_redis(segment3, client_fallback)
1063+
load_flag_sets_redis(flag_sets, client_fallback)
1064+
client_fallback.block_until_ready
1065+
1066+
splits_repository = client_fallback.instance_variable_get(:@splits_repository)
1067+
splits = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json'))
1068+
split = JSON.parse(splits,:symbolize_names => true)[:ff][:d][0]
1069+
split[:trafficAllocation] = nil
1070+
splits_repository.update([split], [], -1)
1071+
1072+
result = client_fallback.get_treatment_with_config('key3', 'with_track_disabled')
1073+
expect(result[:treatment]).to eq('on-global')
1074+
expect(result[:config]).to eq('{"prop": "global"}')
1075+
1076+
sleep 0.5
1077+
impressions = custom_impression_listener.queue
1078+
expect(impressions.size).to eq 1
1079+
expect(impressions[0][:split_name]).to eq('with_track_disabled')
1080+
expect(impressions[0][:treatment][:label]).to eq('fallback - exception')
1081+
end
1082+
end
9951083
end
9961084

9971085
private

spec/splitclient/engine_localhost_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,31 @@
160160
end
161161
end
162162
end
163+
164+
context 'fallback treatment' do
165+
subject { SplitIoClient::SplitFactoryBuilder.build('localhost',
166+
fallback_treatments: SplitIoClient::Engine::Models::FallbackTreatmentsConfiguration.new(
167+
SplitIoClient::Engine::Models::FallbackTreatment.new(
168+
"on-global", '{"prop": "global"}'
169+
),
170+
{:feature => SplitIoClient::Engine::Models::FallbackTreatment.new(
171+
"on-local", '{"prop": "local"}'
172+
)
173+
}
174+
),
175+
split_file: split_file).client
176+
}
177+
178+
let(:split_file) { File.expand_path(File.join(File.dirname(__FILE__), '../test_data/local_treatments/split.yaml')) }
179+
180+
it 'feature does not exist' do
181+
result = subject.get_treatment_with_config('john_doe', 'feature')
182+
expect(result[:treatment]).to eq('on-local')
183+
expect(result[:config]).to eq('{"prop": "local"}')
184+
185+
result = subject.get_treatment_with_config('john_doe', 'feature2')
186+
expect(result[:treatment]).to eq('on-global')
187+
expect(result[:config]).to eq('{"prop": "global"}')
188+
end
189+
end
163190
end

0 commit comments

Comments
 (0)