From 14cee7326d2c81f0320768610afaadfb3bb0d117 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Wed, 14 May 2025 10:40:22 -0700 Subject: [PATCH 01/11] Integrations tests --- .../cache/fetchers/split_fetcher.rb | 1 + lib/splitclient-rb/clients/split_client.rb | 2 + lib/splitclient-rb/engine/api/splits.rb | 19 +- .../matchers/rule_based_segment_matcher.rb | 28 +- lib/splitclient-rb/engine/parser/condition.rb | 2 +- lib/splitclient-rb/engine/parser/evaluator.rb | 2 +- .../helpers/evaluator_helper.rb | 2 +- lib/splitclient-rb/split_factory.rb | 6 +- .../clients/split_client_spec.rb | 3 +- spec/cache/fetchers/segment_fetch_spec.rb | 2 +- spec/engine/auth_api_client_spec.rb | 6 +- spec/engine/matchers/between_matcher_spec.rb | 12 +- .../engine/matchers/combining_matcher_spec.rb | 2 +- spec/engine/matchers/equal_to_matcher_spec.rb | 8 +- .../greater_than_or_equal_to_matcher_spec.rb | 6 +- .../less_than_or_equal_to_matcher_spec.rb | 8 +- .../semver_matchers_integration_spec.rb | 22 +- .../engine/matchers/whitelist_matcher_spec.rb | 2 +- spec/engine/parser/evaluator_spec.rb | 6 +- spec/engine/push_manager_spec.rb | 23 +- spec/engine/sync_manager_spec.rb | 16 +- spec/engine_spec.rb | 18 +- spec/integrations/dedupe_impression_spec.rb | 12 +- spec/integrations/in_memory_client_spec.rb | 129 +++++-- spec/integrations/push_client_spec.rb | 80 ++--- spec/integrations/redis_client_spec.rb | 2 +- spec/splitclient/split_client_spec.rb | 40 ++- spec/splitclient/split_factory_spec.rb | 24 +- spec/splitclient/split_manager_spec.rb | 14 +- spec/splitclient_rb_corner_cases_spec.rb | 4 +- .../rule_base_segments.json | 135 +++++++ .../rule_base_segments2.json | 140 ++++++++ .../rule_base_segments3.json | 108 ++++++ .../rule_based_segments/split_old_spec.json | 328 ++++++++++++++++++ .../datetime_matcher_splits.json | 9 +- .../negate_number_matcher_splits.json | 9 +- .../negative_number_matcher_splits.json | 9 +- .../number_matcher_splits.json | 9 +- .../splits/boolean_matcher/splits.json | 9 +- .../splits/combining_matcher_splits.json | 6 +- .../splits/engine/all_keys_matcher.json | 9 +- .../splits/engine/configurations.json | 9 +- .../splits/engine/dependency_matcher.json | 9 +- .../splits/engine/equal_to_set_matcher.json | 11 +- .../splits/engine/impressions_test.json | 9 +- spec/test_data/splits/engine/killed.json | 9 +- .../engine/segment_deleted_matcher.json | 9 +- .../splits/engine/segment_matcher.json | 9 +- .../splits/engine/segment_matcher2.json | 9 +- .../splits/engine/whitelist_matcher.json | 9 +- .../splits/equal_to_matcher/date_splits.json | 9 +- .../equal_to_matcher/negative_splits.json | 9 +- .../splits/equal_to_matcher/splits.json | 9 +- .../splits/equal_to_matcher/zero_splits.json | 9 +- .../date_splits.json | 9 +- .../negative_splits.json | 9 +- .../splits.json | 9 +- spec/test_data/splits/imp-toggle.json | 6 +- .../date_splits.json | 9 +- .../date_splits2.json | 9 +- .../negative_splits.json | 9 +- .../less_than_or_equal_to_matcher/splits.json | 9 +- .../semver_matchers/semver_between.json | 7 +- .../semver_matchers/semver_equalto.json | 7 +- .../semver_greater_or_equalto.json | 7 +- .../splits/semver_matchers/semver_inlist.json | 7 +- .../semver_less_or_equalto.json | 7 +- spec/test_data/splits/splits4.json | 9 +- .../splits/splits_traffic_allocation.json | 5 +- ...splits_traffic_allocation_one_percent.json | 7 +- .../splits/whitelist_matcher_splits.json | 7 +- 71 files changed, 1212 insertions(+), 311 deletions(-) create mode 100644 spec/test_data/rule_based_segments/rule_base_segments.json create mode 100644 spec/test_data/rule_based_segments/rule_base_segments2.json create mode 100644 spec/test_data/rule_based_segments/rule_base_segments3.json create mode 100644 spec/test_data/rule_based_segments/split_old_spec.json diff --git a/lib/splitclient-rb/cache/fetchers/split_fetcher.rb b/lib/splitclient-rb/cache/fetchers/split_fetcher.rb index 8353d51d..c2772d62 100644 --- a/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +++ b/lib/splitclient-rb/cache/fetchers/split_fetcher.rb @@ -28,6 +28,7 @@ def fetch_splits(fetch_options = { cache_control_headers: false, till: nil }) SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@splits_repository, data[:ff][:d], data[:ff][:t], @config) SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segments_repository, data[:rbs][:d], data[:rbs][:t], @config) @splits_repository.set_segment_names(data[:segment_names]) + @rule_based_segments_repository.set_segment_names(data[:segment_names]) @config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled { segment_names: data[:segment_names], success: true } diff --git a/lib/splitclient-rb/clients/split_client.rb b/lib/splitclient-rb/clients/split_client.rb index b81fbfb2..ed0e1021 100644 --- a/lib/splitclient-rb/clients/split_client.rb +++ b/lib/splitclient-rb/clients/split_client.rb @@ -22,6 +22,7 @@ def initialize(sdk_key, repositories, status_manager, config, impressions_manage @api_key = sdk_key @splits_repository = repositories[:splits] @segments_repository = repositories[:segments] + @rule_based_segments_repository = repositories[:rule_based_segments] @impressions_repository = repositories[:impressions] @events_repository = repositories[:events] @status_manager = status_manager @@ -115,6 +116,7 @@ def destroy @splits_repository.clear @segments_repository.clear + @rule_based_segments_repository.clear SplitIoClient.load_factory_registry SplitIoClient.split_factory_registry.remove(@api_key) diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index 62e3d4a6..0596c9de 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -33,7 +33,7 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till @config.split_logger.log_if_transport("Feature flag changes response: #{result[:ff].to_s}") unless result[:rbs][:d].empty? - @config.split_logger.log_if_debug("#{result[:ff][:d].length} rule based segments retrieved. since=#{since_rbs}") + @config.split_logger.log_if_debug("#{result[:rbs][:d].length} rule based segments retrieved. since=#{since_rbs}") end @config.split_logger.log_if_transport("rule based segments changes response: #{result[:rbs].to_s}") @@ -56,15 +56,24 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till def objects_with_segment_names(objects_json) parsed_objects = JSON.parse(objects_json, symbolize_names: true) + parsed_objects[:segment_names] = Set.new parsed_objects[:segment_names] = parsed_objects[:ff][:d].each_with_object(Set.new) do |split, splits| splits << Helpers::Util.segment_names_by_object(split, "IN_SEGMENT") end.flatten - if not parsed_objects[:ff][:rbs].nil? - parsed_objects[:segment_names].merge parsed_objects[:ff][:rbs].each_with_object(Set.new) do |rule_based_segment, rule_based_segments| - rule_based_segments << Helpers::Util.segment_names_by_object(rule_based_segment, "IN_SEGMENT") - end.flatten + + parsed_objects[:rbs][:d].each do |rule_based_segment| + parsed_objects[:segment_names].merge Helpers::Util.segment_names_by_object(rule_based_segment, "IN_SEGMENT") + end + + parsed_objects[:rbs][:d].each do |rule_based_segment| + rule_based_segment[:excluded][:segments].each do |segment| + if segment[:type] == "standard" + parsed_objects[:segment_names].add(segment[:name]) + end + end end + parsed_objects end end diff --git a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb index 7900fe96..69c72272 100644 --- a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +++ b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb @@ -25,13 +25,18 @@ def match?(args) rule_based_segment = @rule_based_segments_repository.get_rule_based_segment(@segment_name) return false if rule_based_segment.nil? - return false if rule_based_segment[:excluded][:keys].include?([args[:value]]) + if args[:value].nil? or args[:value].empty? + key = args[:matching_key] + else + key = args[:value] + end + return false if rule_based_segment[:excluded][:keys].include?(key) rule_based_segment[:excluded][:segments].each do |segment| - return false if segment[:type] == 'standard' and @segments_repository.in_segment?(segment[:name], args[:value]) + return false if segment[:type] == 'standard' and @segments_repository.in_segment?(segment[:name], key) if segment[:type] == 'rule-based' - return true if match_rbs(@rule_based_segments_repository.get_rule_based_segment(segment[:name])[:conditions], args) + return false if match_rbs(@rule_based_segments_repository.get_rule_based_segment(segment[:name]), args) end end @@ -49,18 +54,13 @@ def match?(args) private - def match_rbs(conditions, args) - conditions.each do |condition| - next if condition.empty? - - return true if Helpers::EvaluatorHelper::matcher_type(SplitIoClient::Condition.new(condition, @config), - @segments_repository, @rule_based_segments_repository).match?( - matching_key: args[:matching_key], - bucketing_key: args[:value], - attributes: args[:attributes] + def match_rbs(rule_based_segment, args) + rbs_matcher = RuleBasedSegmentMatcher.new(@segments_repository, @rule_based_segments_repository, rule_based_segment[:name], @config) + return rbs_matcher.match?( + matching_key: args[:matching_key], + bucketing_key: args[:value], + attributes: args[:attributes] ) - end - return false end end end diff --git a/lib/splitclient-rb/engine/parser/condition.rb b/lib/splitclient-rb/engine/parser/condition.rb index 926dd206..0caaabe8 100644 --- a/lib/splitclient-rb/engine/parser/condition.rb +++ b/lib/splitclient-rb/engine/parser/condition.rb @@ -253,7 +253,7 @@ def negate # @return [void] def set_partitions partitions_list = [] - return partitions_list unless @data.key?('partitions') + return partitions_list unless @data.key?(:partitions) or @data.key?('partitions') @data[:partitions].each do |p| partition = SplitIoClient::Partition.new(p) diff --git a/lib/splitclient-rb/engine/parser/evaluator.rb b/lib/splitclient-rb/engine/parser/evaluator.rb index b9508e38..ec7636cd 100644 --- a/lib/splitclient-rb/engine/parser/evaluator.rb +++ b/lib/splitclient-rb/engine/parser/evaluator.rb @@ -5,6 +5,7 @@ class Evaluator def initialize(segments_repository, splits_repository, rb_segment_repository, config) @splits_repository = splits_repository @segments_repository = segments_repository + @rb_segment_repository = rb_segment_repository @config = config end @@ -58,7 +59,6 @@ def match(split, keys, attributes) in_rollout = true end - condition_matched = Helpers::EvaluatorHelper::matcher_type(condition, @segments_repository, @rb_segment_repository).match?( matching_key: keys[:matching_key], bucketing_key: keys[:bucketing_key], diff --git a/lib/splitclient-rb/helpers/evaluator_helper.rb b/lib/splitclient-rb/helpers/evaluator_helper.rb index e9c55cfc..331c7987 100644 --- a/lib/splitclient-rb/helpers/evaluator_helper.rb +++ b/lib/splitclient-rb/helpers/evaluator_helper.rb @@ -8,7 +8,7 @@ def self.matcher_type(condition, segments_repository, rb_segment_repository) segments_repository.adapter.pipelined do condition.matchers.each do |matcher| matchers << if matcher[:negate] - condition.negation_matcher(matcher_instance(matcher[:matcherType], condition, matcher)) + condition.negation_matcher(matcher_instance(matcher[:matcherType], condition, matcher, segments_repository, rb_segment_repository)) else matcher_instance(matcher[:matcherType], condition, matcher, segments_repository, rb_segment_repository) end diff --git a/lib/splitclient-rb/split_factory.rb b/lib/splitclient-rb/split_factory.rb index 22be6ca7..7c8a4306 100644 --- a/lib/splitclient-rb/split_factory.rb +++ b/lib/splitclient-rb/split_factory.rb @@ -55,7 +55,7 @@ def initialize(api_key, config_hash = {}) @status_manager = Engine::StatusManager.new(@config) @split_validator = SplitIoClient::Validators.new(@config) - @evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @config) + @evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @rule_based_segment_repository, @config) start! @@ -179,7 +179,7 @@ def build_telemetry_components end def build_fetchers - @split_fetcher = SplitFetcher.new(@splits_repository, @rule_based_segments_repository, @api_key, @config, @runtime_producer) + @split_fetcher = SplitFetcher.new(@splits_repository, @rule_based_segment_repository, @api_key, @config, @runtime_producer) @segment_fetcher = SegmentFetcher.new(@segments_repository, @api_key, @config, @runtime_producer) end @@ -221,7 +221,7 @@ def build_repositories end @splits_repository = SplitsRepository.new(@config, @flag_sets_repository, @flag_sets_filter) @segments_repository = SegmentsRepository.new(@config) - @rule_based_segment_repository = RuleBasedSegmentRepository.new(@config) + @rule_based_segment_repository = RuleBasedSegmentsRepository.new(@config) @impressions_repository = ImpressionsRepository.new(@config) @events_repository = EventsRepository.new(@config, @api_key, @runtime_producer) end diff --git a/spec/allocations/splitclient-rb/clients/split_client_spec.rb b/spec/allocations/splitclient-rb/clients/split_client_spec.rb index 0dd15231..5d38f377 100644 --- a/spec/allocations/splitclient-rb/clients/split_client_spec.rb +++ b/spec/allocations/splitclient-rb/clients/split_client_spec.rb @@ -10,6 +10,7 @@ let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) } let(:segments_repository) { SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) } let(:impressions_repository) { SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) } + let(:rule_based_segments_repository) { SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) } let(:impression_counter) { SplitIoClient::Engine::Common::ImpressionCounter.new } let(:evaluation_producer) { SplitIoClient::Telemetry::EvaluationProducer.new(config) } let(:impression_observer) { SplitIoClient::Observers::ImpressionObserver.new } @@ -19,7 +20,7 @@ let(:api_key) { 'SplitClient-key' } let(:telemetry_api) { SplitIoClient::Api::TelemetryApi.new(config, api_key, runtime_producer) } let(:impressions_api) { SplitIoClient::Api::Impressions.new(api_key, config, runtime_producer) } - let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) } + let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, rule_based_segments_repository, config) } let(:sender_adapter) do SplitIoClient::Cache::Senders::ImpressionsSenderAdapter.new(config, telemetry_api, diff --git a/spec/cache/fetchers/segment_fetch_spec.rb b/spec/cache/fetchers/segment_fetch_spec.rb index 031bb2a8..6280866b 100644 --- a/spec/cache/fetchers/segment_fetch_spec.rb +++ b/spec/cache/fetchers/segment_fetch_spec.rb @@ -26,7 +26,7 @@ stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=1473863075059') .to_return(status: 200, body: segments_json2) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_with_segments_json) end diff --git a/spec/engine/auth_api_client_spec.rb b/spec/engine/auth_api_client_spec.rb index 0235c130..eaa5ba70 100644 --- a/spec/engine/auth_api_client_spec.rb +++ b/spec/engine/auth_api_client_spec.rb @@ -15,7 +15,7 @@ let(:telemetry_runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } it 'authenticate success' do - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 200, body: body_response) auth_api_client = subject.new(config, telemetry_runtime_producer) response = auth_api_client.authenticate(api_key) @@ -26,7 +26,7 @@ end it 'auth server return 500' do - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 500) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 500) auth_api_client = subject.new(config, telemetry_runtime_producer) response = auth_api_client.authenticate(api_key) @@ -36,7 +36,7 @@ end it 'auth server return 401' do - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 401) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 401) auth_api_client = subject.new(config, telemetry_runtime_producer) response = auth_api_client.authenticate(api_key) diff --git a/spec/engine/matchers/between_matcher_spec.rb b/spec/engine/matchers/between_matcher_spec.rb index 9e16e550..765ea2d6 100644 --- a/spec/engine/matchers/between_matcher_spec.rb +++ b/spec/engine/matchers/between_matcher_spec.rb @@ -41,9 +41,7 @@ before do # stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) # .to_return(status: 200, body: number_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges') - .to_return(status: 200, body: number_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: number_matcher_splits) subject.block_until_ready sleep 1 @@ -69,7 +67,9 @@ let(:non_matching_low_value_negative_attributes) { { income: -999 } } before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since.*/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since.*/) + .to_return(status: 200, body: negative_number_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: negative_number_matcher_splits) subject.block_until_ready sleep 1 @@ -97,7 +97,9 @@ let(:non_matching_high_value_attributes) { { created: 1_459_775_460 } } # "2016/04/04T13:11Z" before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since/) + .to_return(status: 200, body: datetime_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: datetime_matcher_splits) subject.block_until_ready sleep 1 diff --git a/spec/engine/matchers/combining_matcher_spec.rb b/spec/engine/matchers/combining_matcher_spec.rb index bdaccaa7..ab04b2a3 100644 --- a/spec/engine/matchers/combining_matcher_spec.rb +++ b/spec/engine/matchers/combining_matcher_spec.rb @@ -19,7 +19,7 @@ before do stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1') .to_return(status: 200, body: segments_json) - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') diff --git a/spec/engine/matchers/equal_to_matcher_spec.rb b/spec/engine/matchers/equal_to_matcher_spec.rb index 043b39df..6f249c6e 100644 --- a/spec/engine/matchers/equal_to_matcher_spec.rb +++ b/spec/engine/matchers/equal_to_matcher_spec.rb @@ -37,7 +37,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') @@ -64,7 +64,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: zero_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') @@ -90,7 +90,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: negative_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') @@ -117,7 +117,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: date_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') diff --git a/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb b/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb index 5283bfb9..9503b5c7 100644 --- a/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb +++ b/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb @@ -35,7 +35,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -61,7 +61,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: negative_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -92,7 +92,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: date_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) diff --git a/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb b/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb index 60936dc0..13bee2cd 100644 --- a/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb +++ b/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb @@ -37,7 +37,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -64,7 +64,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: negative_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -93,7 +93,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: date_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -119,7 +119,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: date_splits2_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) diff --git a/spec/engine/matchers/semver_matchers_integration_spec.rb b/spec/engine/matchers/semver_matchers_integration_spec.rb index 86909af5..04a76af4 100644 --- a/spec/engine/matchers/semver_matchers_integration_spec.rb +++ b/spec/engine/matchers/semver_matchers_integration_spec.rb @@ -51,11 +51,11 @@ context 'equal to matcher' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since\.*/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since\.*/) .to_return(status: 200, body: semver_equalto_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: semver_equalto_matcher_splits) - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1675259356568") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1675259356568&rbSince=-1") .to_return(status: 200, body: semver_equalto_matcher_splits) sleep 1 subject.block_until_ready @@ -75,9 +75,9 @@ context 'greater than or equal to matcher' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since/) .to_return(status: 200, body: semver_greater_or_equalto_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: semver_greater_or_equalto_matcher_splits) sleep 1 subject.block_until_ready @@ -98,9 +98,9 @@ context 'less than or equal to matcher' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since=-1&rbSince=-1/) .to_return(status: 200, body: semver_less_or_equalto_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: semver_less_or_equalto_matcher_splits) sleep 1 subject.block_until_ready @@ -121,9 +121,9 @@ context 'in list matcher' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since=-1&rbSince=-1/) .to_return(status: 200, body: semver_inlist_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: semver_inlist_matcher_splits) sleep 1 subject.block_until_ready @@ -144,9 +144,9 @@ context 'between matcher' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since=-1&rbSince=-1/) .to_return(status: 200, body: semver_between_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: semver_between_matcher_splits) sleep 1 subject.block_until_ready diff --git a/spec/engine/matchers/whitelist_matcher_spec.rb b/spec/engine/matchers/whitelist_matcher_spec.rb index 25f4a4ba..90f40f65 100644 --- a/spec/engine/matchers/whitelist_matcher_spec.rb +++ b/spec/engine/matchers/whitelist_matcher_spec.rb @@ -22,7 +22,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) diff --git a/spec/engine/parser/evaluator_spec.rb b/spec/engine/parser/evaluator_spec.rb index 99f5cdfb..a6beabe9 100644 --- a/spec/engine/parser/evaluator_spec.rb +++ b/spec/engine/parser/evaluator_spec.rb @@ -32,12 +32,12 @@ context 'dependency matcher' do it 'uses cache' do allow(evaluator.instance_variable_get(:@splits_repository)) - .to receive(:get_split).and_return(split_data[:splits][0]) + .to receive(:get_split).and_return(split_data[:ff][:d][0]) expect(evaluator).to receive(:match).exactly(2).times - evaluator.evaluate_feature_flag({ bucketing_key: nil, matching_key: 'fake_user_id_1' }, split_data[:splits][0]) + evaluator.evaluate_feature_flag({ bucketing_key: nil, matching_key: 'fake_user_id_1' }, split_data[:ff][:d][0]) - evaluator.evaluate_feature_flag({ bucketing_key: nil, matching_key: 'fake_user_id_1' }, split_data[:splits][1]) + evaluator.evaluate_feature_flag({ bucketing_key: nil, matching_key: 'fake_user_id_1' }, split_data[:ff][:d][1]) end end end diff --git a/spec/engine/push_manager_spec.rb b/spec/engine/push_manager_spec.rb index a1a6d9e7..4cc3f9db 100644 --- a/spec/engine/push_manager_spec.rb +++ b/spec/engine/push_manager_spec.rb @@ -14,14 +14,15 @@ let(:flag_set_filter) {SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) } let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) } let(:segments_repository) { SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) } + let(:rule_based_segments_repository) { SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) } let(:runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } - let(:split_fetcher) { SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_repository, api_key, config, runtime_producer) } + let(:split_fetcher) { SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_repository, rule_based_segments_repository, api_key, config, runtime_producer) } let(:segment_fetcher) { SplitIoClient::Cache::Fetchers::SegmentFetcher.new(segments_repository, api_key, config, runtime_producer) } - let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(split_fetcher, config, splits_repository, runtime_producer, segment_fetcher) } + let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(split_fetcher, config, splits_repository, runtime_producer, segment_fetcher, rule_based_segments_repository) } let(:segments_worker) { SplitIoClient::SSE::Workers::SegmentsWorker.new(segment_fetcher, config, segments_repository) } let(:push_status_queue) { Queue.new } let(:notification_manager_keeper) { SplitIoClient::SSE::NotificationManagerKeeper.new(config, runtime_producer, push_status_queue) } - let(:repositories) { { splits: splits_repository, segments: segments_repository } } + let(:repositories) { { splits: splits_repository, segments: segments_repository, rule_based_segments: rule_based_segments_repository } } let(:impression_counter) { SplitIoClient::Engine::Common::ImpressionCounter.new } let(:params) do { @@ -43,7 +44,7 @@ send_mock_content(res, 'content') end - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 200, body: body_response) config.streaming_service_url = server.base_uri sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) @@ -51,7 +52,7 @@ push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.3")).to have_been_made.times(1) sleep(1.5) expect(connected).to eq(true) @@ -61,14 +62,14 @@ end it 'must not connect to server. Auth server return 500' do - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 500) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 500) sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.3")).to have_been_made.times(1) sleep(1.5) @@ -77,14 +78,14 @@ end it 'must not connect to server. Auth server return 401' do - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 401) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 401) sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.3")).to have_been_made.times(1) sleep(1.5) @@ -100,14 +101,14 @@ send_mock_content(res, 'content') end - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 200, body: body_response) config.streaming_service_url = server.base_uri sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.3")).to have_been_made.times(1) sleep(1.5) diff --git a/spec/engine/sync_manager_spec.rb b/spec/engine/sync_manager_spec.rb index d472de01..68169a7c 100644 --- a/spec/engine/sync_manager_spec.rb +++ b/spec/engine/sync_manager_spec.rb @@ -20,6 +20,7 @@ let(:flag_set_filter) {SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) } let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) } let(:segments_repository) { SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) } + let(:rule_based_segments_repository) { SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) } let(:impressions_repository) { SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) } let(:telemetry_runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } let(:events_repository) { SplitIoClient::Cache::Repositories::EventsRepository.new(config, api_key, telemetry_runtime_producer) } @@ -29,12 +30,13 @@ splits: splits_repository, segments: segments_repository, impressions: impressions_repository, - events: events_repository + events: events_repository, + rule_based_segments: rule_based_segments_repository } end let(:sync_params) do { - split_fetcher: SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_repository, api_key, config, telemetry_runtime_producer), + split_fetcher: SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_repository, rule_based_segments_repository, api_key, config, telemetry_runtime_producer), segment_fetcher: SplitIoClient::Cache::Fetchers::SegmentFetcher.new(segments_repository, api_key, config, telemetry_runtime_producer), imp_counter: impression_counter, telemetry_runtime_producer: telemetry_runtime_producer, @@ -50,7 +52,7 @@ let(:telemetry_api) { SplitIoClient::Api::TelemetryApi.new(config, api_key, telemetry_runtime_producer) } let(:telemetry_synchronizer) { SplitIoClient::Telemetry::Synchronizer.new(config, telemetry_consumers, init_producer, repositories, telemetry_api, 0, 0) } let(:status_manager) { SplitIoClient::Engine::StatusManager.new(config) } - let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository, telemetry_runtime_producer, sync_params[:segment_fetcher]) } + let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository, telemetry_runtime_producer, sync_params[:segment_fetcher], rule_based_segments_repository) } let(:segments_worker) { SplitIoClient::SSE::Workers::SegmentsWorker.new(synchronizer, config, segments_repository) } let(:notification_processor) { SplitIoClient::SSE::NotificationProcessor.new(config, splits_worker, segments_worker) } let(:event_parser) { SplitIoClient::SSE::EventSource::EventParser.new(config) } @@ -68,7 +70,7 @@ mock_segment_changes('segment2', segment2, '-1') mock_segment_changes('segment2', segment2, '1470947453878') mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.3").to_return(status: 200, body: body_response) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') end @@ -84,7 +86,7 @@ sync_manager.start sleep(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.once expect(config.threads.size).to eq(11) config.threads.values.each { |thread| Thread.kill(thread) } @@ -104,7 +106,7 @@ sync_manager.start sleep(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.once expect(config.threads.size).to eq(8) config.threads.values.each { |thread| Thread.kill(thread) } @@ -136,7 +138,7 @@ private def mock_split_changes_with_since(splits_json, since) - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=#{since}") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=#{since}&rbSince=-1") .to_return(status: 200, body: splits_json) end diff --git a/spec/engine_spec.rb b/spec/engine_spec.rb index b9999044..7909d64d 100644 --- a/spec/engine_spec.rb +++ b/spec/engine_spec.rb @@ -46,7 +46,7 @@ @mode = cache_adapter.equal?(:memory) ? :standalone : :consumer stub_request(:any, /https:\/\/telemetry.*/).to_return(status: 200, body: 'ok') stub_request(:any, /https:\/\/events.*/).to_return(status: 200, body: '') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since=-1&rbSince=-1/) .to_return(status: 200, body: '') stub_request(:post, "https://telemetry.split.io/api/v1/metrics/config") .to_return(status: 200, body: '') @@ -128,7 +128,7 @@ context '#get_treatment' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/).to_return(status: 200, body: '') + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.3&since=-1&rbSince=-1/).to_return(status: 200, body: '') load_splits(all_keys_matcher_json, flag_sets_json) subject.block_until_ready @@ -928,7 +928,7 @@ end it 'returns control' do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: all_keys_matcher_json) subject.block_until_ready @@ -942,7 +942,7 @@ describe 'redis outage' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: all_keys_matcher_json) end @@ -955,7 +955,7 @@ describe 'events' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: all_keys_matcher_json) subject.block_until_ready end @@ -985,7 +985,7 @@ context '#track' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: all_keys_matcher_json) subject.block_until_ready end @@ -1192,7 +1192,7 @@ end before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since.*/) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: all_keys_matcher_json) end @@ -1270,7 +1270,7 @@ def load_splits(splits_json, flag_sets_json) if @mode.equal?(:standalone) # stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since.*/) - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=-1") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1") .to_return(status: 200, body: splits_json) else add_splits_to_repository(splits_json) @@ -1288,7 +1288,7 @@ def load_segments(segments_json) end def add_splits_to_repository(splits_json) - splits = JSON.parse(splits_json, symbolize_names: true)[:splits] + splits = JSON.parse(splits_json, symbolize_names: true)[:ff][:d] splits_repository = subject.instance_variable_get(:@splits_repository) diff --git a/spec/integrations/dedupe_impression_spec.rb b/spec/integrations/dedupe_impression_spec.rb index 399d3045..86e6b935 100644 --- a/spec/integrations/dedupe_impression_spec.rb +++ b/spec/integrations/dedupe_impression_spec.rb @@ -33,8 +33,8 @@ context 'checking logic impressions' do it 'get_treament should post 7 impressions - debug mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=-1").to_return(status: 200, body: splits, headers: {}) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1").to_return(status: 200, body: splits, headers: {}) factory = SplitIoClient::SplitFactory.new('test_api_key_debug-1', streaming_enabled: false, impressions_mode: :debug) debug_client = factory.client @@ -61,7 +61,7 @@ it 'get_treaments should post 9 impressions - debug mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1').to_return(status: 200, body: '') factory = SplitIoClient::SplitFactory.new('test_api_key_debug-2', streaming_enabled: false, impressions_mode: :debug) debug_client = factory.client @@ -81,7 +81,7 @@ it 'get_treament should post 3 impressions - optimized mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1').to_return(status: 200, body: '') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage').to_return(status: 200, body: '') factory = SplitIoClient::SplitFactory.new('test_api_key-1', streaming_enabled: false, impressions_mode: :optimized, impressions_refresh_rate: 60) @@ -113,7 +113,7 @@ it 'get_treaments should post 8 impressions - optimized mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1').to_return(status: 200, body: '') factory = SplitIoClient::SplitFactory.new('test_api_key-2', streaming_enabled: false, impressions_mode: :optimized) client = factory.client @@ -149,7 +149,7 @@ private def mock_split_changes_v2(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_json) end diff --git a/spec/integrations/in_memory_client_spec.rb b/spec/integrations/in_memory_client_spec.rb index d70e6c76..ab0538ae 100644 --- a/spec/integrations/in_memory_client_spec.rb +++ b/spec/integrations/in_memory_client_spec.rb @@ -52,7 +52,7 @@ context '#get_treatment' do it 'returns CONTROL when server return 500' do - # stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + # stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916").to_return(status: 200, body: 'ok') mock_split_changes_error expect(client.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'control' @@ -67,7 +67,7 @@ end it 'returns treatments with FACUNDO_TEST feature and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'on' expect(client.get_treatment('mauro_test', 'FACUNDO_TEST')).to eq 'off' @@ -91,7 +91,7 @@ end it 'returns treatments with Test_Save_1 feature and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment('1', 'Test_Save_1')).to eq 'on' expect(client.get_treatment('24', 'Test_Save_1')).to eq 'off' @@ -115,7 +115,7 @@ end it 'returns treatments with input validations' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'on' expect(client.get_treatment('', 'FACUNDO_TEST')).to eq 'control' @@ -143,7 +143,7 @@ end it 'returns CONTROL with treatment doesnt exist' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') expect(client.get_treatment('nico_test', 'random_treatment')).to eq 'control' impressions = custom_impression_listener.queue @@ -151,7 +151,7 @@ end it 'with multiple factories returns on' do -# stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') +# stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916").to_return(status: 200, body: 'ok') local_log = StringIO.new logger = Logger.new(local_log) @@ -231,7 +231,7 @@ context '#get_treatment_with_config' do it 'returns treatments and configs with FACUNDO_TEST treatment and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('nico_test', 'FACUNDO_TEST')).to eq( treatment: 'on', @@ -261,7 +261,7 @@ end it 'returns treatments and configs with MAURO_TEST treatment and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('mauro', 'MAURO_TEST')).to eq( @@ -292,7 +292,7 @@ end it 'returns treatments with input validations' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('nico_test', 'FACUNDO_TEST')).to eq( @@ -339,7 +339,7 @@ end it 'returns CONTROL with treatment doesnt exist' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('nico_test', 'random_treatment')).to eq( @@ -353,7 +353,7 @@ end it 'returns CONTROL when server return 500' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') mock_split_changes_error expect(client.get_treatment_with_config('nico_test', 'FACUNDO_TEST')).to eq( @@ -375,7 +375,7 @@ context '#get_treatments' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -479,7 +479,8 @@ context '#get_treatments_by_flag_set' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + mock_split_changes(splits) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -564,7 +565,7 @@ context '#get_treatments_by_flag_sets' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -647,7 +648,8 @@ context '#get_treatments_with_config_by_flag_set' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') + stub_request(:post, "https://events.split.io/api/testImpressions/bulk").to_return(status: 200, body: "", headers: {}) end it 'returns treatments and check impressions' do @@ -757,7 +759,7 @@ context '#get_treatments_with_config_by_flag_sets' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -861,7 +863,7 @@ context '#get_treatments_with_config' do it 'returns treatments and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready result = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST MAURO_TEST Test_Save_1]) expect(result[:FACUNDO_TEST]).to eq( @@ -901,7 +903,7 @@ end it 'returns treatments with input validation' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready result1 = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST "" nil]) result2 = client.get_treatments_with_config('', %w["" MAURO_TEST Test_Save_1]) @@ -940,7 +942,7 @@ end it 'returns CONTROL with treatment doesnt exist' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') client.block_until_ready result = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST random_treatment]) @@ -965,7 +967,7 @@ end it 'returns CONTROL when server return 500' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') mock_split_changes_error result = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST MAURO_TEST Test_Save_1]) @@ -1085,7 +1087,7 @@ context '#track' do it 'returns true' do stub_request(:post, 'https://events.split.io/api/events/bulk').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1').to_return(status: 200, body: '') properties = { property_1: 1, @@ -1144,7 +1146,7 @@ flag_sets_filter: ['set_3', '@3we']) end before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&sets=set_3') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1&sets=set_3') .to_return(status: 200, body: splits) mock_segment_changes('segment1', segment1, '-1') mock_segment_changes('segment1', segment1, '1470947453877') @@ -1204,7 +1206,7 @@ context 'impressions toggle' do it 'optimized mode' do splits_imp_toggle = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json')) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_imp_toggle) factory_imp_toggle = SplitIoClient::SplitFactory.new('test_api_key', @@ -1236,9 +1238,10 @@ expect(imp_count.keys()[0].include? ('with_track_disabled')).to eq(true) expect(imp_count.length).to eq(1) end + it 'debug mode' do splits_imp_toggle = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json')) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_imp_toggle) factory_imp_toggle = SplitIoClient::SplitFactory.new('test_api_key', @@ -1272,7 +1275,7 @@ end it 'none mode' do splits_imp_toggle = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json')) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_imp_toggle) factory_imp_toggle = SplitIoClient::SplitFactory.new('test_api_key', @@ -1306,17 +1309,89 @@ expect(imp_count.length).to eq(3) end end + + context 'rule based segments' do + it 'using segment in excluded' do + splits_rbs = File.read(File.join(SplitIoClient.root, 'spec/test_data/rule_based_segments/rule_base_segments3.json')) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return(status: 200, body: splits_rbs) + stub_request(:get, "https://sdk.split.io/api/splitChanges?rbSince=1506703262916&s=1.3&since=1506703262916") + .to_return(status: 200, body: "") + stub_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=-1') + .to_return(status: 200, body: '{"name": "segment1","added": ["pato@split.io"],"removed": [],"since": -1,"till": 1470947453877}') + stub_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=1470947453877') + .to_return(status: 200, body: '{"name": "segment1","added": [],"removed": [],"since": 1470947453877,"till": 1470947453877}') + factory_rbs = + SplitIoClient::SplitFactory.new('test_api_key', + impressions_mode: :optimized, + features_refresh_rate: 9999, + telemetry_refresh_rate: 99999, + impressions_refresh_rate: 99999, + streaming_enabled: false) + + client_rbs = factory_rbs.client + client_rbs.block_until_ready + + expect(client_rbs.get_treatment('bilal@split.io', 'rbs_feature_flag', {:email => 'bilal@split.io'})).to eq('on') + expect(client_rbs.get_treatment('mauro@split.io', 'rbs_feature_flag', {:email => 'mauro@split.io'})).to eq('off') + expect(client_rbs.get_treatment('pato@split.io', 'rbs_feature_flag', {:email => 'pato@split.io'})).to eq('off') + end + + it 'using rb segment in excluded' do + splits_rbs = File.read(File.join(SplitIoClient.root, 'spec/test_data/rule_based_segments/rule_base_segments2.json')) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return(status: 200, body: splits_rbs) + stub_request(:get, "https://sdk.split.io/api/splitChanges?rbSince=1506703262916&s=1.3&since=1506703262916") + .to_return(status: 200, body: "") + factory_rbs = + SplitIoClient::SplitFactory.new('test_api_key', + impressions_mode: :optimized, + features_refresh_rate: 9999, + telemetry_refresh_rate: 99999, + impressions_refresh_rate: 99999, + streaming_enabled: false) + + client_rbs = factory_rbs.client + client_rbs.block_until_ready + + expect(client_rbs.get_treatment('bilal@split.io', 'rbs_feature_flag', {:email => 'bilal@split.io'})).to eq('off') + expect(client_rbs.get_treatment('mauro@split.io', 'rbs_feature_flag', {:email => 'mauro@split.io'})).to eq('off') + expect(client_rbs.get_treatment('bilal', 'rbs_feature_flag', {:email => 'bilal'})).to eq('on') + expect(client_rbs.get_treatment('bilal2@split.io', 'rbs_feature_flag', {:email => 'bilal2split.io'})).to eq('on') + end + + it 'using rb segment in condition' do + splits_rbs = File.read(File.join(SplitIoClient.root, 'spec/test_data/rule_based_segments/rule_base_segments.json')) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return(status: 200, body: splits_rbs) + stub_request(:get, "https://sdk.split.io/api/splitChanges?rbSince=1506703262916&s=1.3&since=1506703262916") + .to_return(status: 200, body: "") + factory_rbs = + SplitIoClient::SplitFactory.new('test_api_key', + impressions_mode: :optimized, + features_refresh_rate: 9999, + telemetry_refresh_rate: 99999, + impressions_refresh_rate: 99999, + streaming_enabled: false) + + client_rbs = factory_rbs.client + client_rbs.block_until_ready + + expect(client_rbs.get_treatment('bilal@split.io', 'rbs_feature_flag', {:email => 'bilal@split.io'})).to eq('on') + expect(client_rbs.get_treatment('mauro@split.io', 'rbs_feature_flag', {:email => 'mauro@split.io'})).to eq('off') + end + end end private def mock_split_changes(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_json) end def mock_split_changes_error - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 500) end diff --git a/spec/integrations/push_client_spec.rb b/spec/integrations/push_client_spec.rb index 721340b2..f62d6d60 100644 --- a/spec/integrations/push_client_spec.rb +++ b/spec/integrations/push_client_spec.rb @@ -51,14 +51,14 @@ mock_splits_request(splits2, '1585948850109') mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_update_must_fetch) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -74,9 +74,9 @@ client.block_until_ready sleep(2) expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.at_least_times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.at_least_times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850109&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850110&rbSince=-1')).to have_been_made.times(1) client.destroy end end @@ -91,7 +91,7 @@ send_content(res, event_split_update_must_not_fetch) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -105,9 +105,9 @@ client.block_until_ready(1) sleep(1) expect(client.get_treatment('admin', 'push_test')).to eq('on') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850109&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850110&rbSince=-1')).to have_been_made.times(0) client.destroy end end @@ -123,7 +123,7 @@ send_content(res, event_split_update_missing_change_number) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -137,9 +137,9 @@ client.block_until_ready(1) sleep(1) expect(client.get_treatment('admin', 'push_test')).to eq('on') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850109&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850110&rbSince=-1')).to have_been_made.times(0) end end @@ -149,9 +149,9 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111").to_return(status: 200, body: '') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1").to_return(status: 200, body: '') stub_request(:get, "https://sdk.split.io/api/segmentChanges/bilal_segment?since=-1").to_return(status: 200, body: '') - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) mock_server do |server| @@ -186,13 +186,13 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_iff_update_incorrect_pcn) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -215,13 +215,13 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_iff_update_missing_definition) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -244,13 +244,13 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_iff_update_incorrect_compression) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -280,7 +280,7 @@ send_content(res, event_split_kill_must_fetch) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -293,9 +293,9 @@ client.block_until_ready sleep(2) expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.at_least_times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850109&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850110&rbSince=-1')).to have_been_made.at_least_times(1) client.destroy end end @@ -304,14 +304,14 @@ mock_splits_request(splits, -1) mock_splits_request(splits2, 1_585_948_850_109) mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850110&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_kill_must_not_fetch) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -325,9 +325,9 @@ client.block_until_ready(1) sleep(2) expect(client.get_treatment('admin', 'push_test')).to eq('on') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850109&rbSince=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850110&rbSince=-1')).to have_been_made.times(0) client.destroy end end @@ -346,7 +346,7 @@ send_content(res, event_segment_update_must_fetch) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -375,7 +375,7 @@ send_content(res, event_segment_update_must_not_fetch) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -400,14 +400,14 @@ mock_splits_request(splits2, 1_585_948_850_109) mock_splits_request(splits3, 1_585_948_850_110) mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_occupancy_with_publishers) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -436,7 +436,7 @@ send_content(res, event_occupancy_without_publishers) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -467,7 +467,7 @@ send_content(res, event_control_STREAMING_PAUSED) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -496,7 +496,7 @@ send_content(res, event_control_STREAMING_RESUMED) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -519,14 +519,14 @@ mock_splits_request(splits2, 1_585_948_850_109) mock_splits_request(splits3, 1_585_948_850_110) mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1585948850111&rbSince=-1').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_control_STREAMING_DISABLED) end - stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.3").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -559,7 +559,7 @@ def send_content(res, content) end def mock_splits_request(splits_json, since) - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=#{since}") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=#{since}&rbSince=-1") .to_return(status: 200, body: splits_json) end diff --git a/spec/integrations/redis_client_spec.rb b/spec/integrations/redis_client_spec.rb index b19733db..e23c1525 100644 --- a/spec/integrations/redis_client_spec.rb +++ b/spec/integrations/redis_client_spec.rb @@ -997,7 +997,7 @@ private def load_splits_redis(splits_json, cli) - splits = JSON.parse(splits_json, symbolize_names: true)[:splits] + splits = JSON.parse(splits_json, symbolize_names: true)[:ff][:d] splits_repository = cli.instance_variable_get(:@splits_repository) diff --git a/spec/splitclient/split_client_spec.rb b/spec/splitclient/split_client_spec.rb index d8d7123d..fd19dc0c 100644 --- a/spec/splitclient/split_client_spec.rb +++ b/spec/splitclient/split_client_spec.rb @@ -10,19 +10,20 @@ let(:flag_set_filter) {SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) } let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) } let(:impressions_repository) {SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) } + let(:rule_based_segments_repository) { SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) } let(:runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } let(:events_repository) { SplitIoClient::Cache::Repositories::EventsRepository.new(config, 'sdk_key', runtime_producer) } let(:impression_manager) { SplitIoClient::Engine::Common::ImpressionManager.new(config, impressions_repository, SplitIoClient::Engine::Common::NoopImpressionCounter.new, runtime_producer, SplitIoClient::Observers::NoopImpressionObserver.new, SplitIoClient::Engine::Impressions::NoopUniqueKeysTracker.new) } let(:evaluation_producer) { SplitIoClient::Telemetry::EvaluationProducer.new(config) } - let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) } - let(:split_client) { SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) } + let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, rule_based_segments_repository, config) } + let(:split_client) { SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository, :rule_based_segments => rule_based_segments_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) } let(:splits) do File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/splits.json')) end before do - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][2]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][2]], [], -1) end it 'check getting treatments' do @@ -56,14 +57,14 @@ end it 'posting impressions and events' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits) stub_request(:post, 'https://events.split.io/api/events/bulk').to_return(status: 200, body: '') stub_request(:post, 'https://events.split.io/api/testImpressions/bulk').to_return(status: 200, body: '') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage').to_return(status: 200, body: '') - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916sets=set_3&").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1506703262916&rbSince=-1&sets=set_3&").to_return(status: 200, body: 'ok') mock_segment_changes('segment1', segment1, '-1') mock_segment_changes('segment1', segment1, '1470947453877') mock_segment_changes('segment2', segment2, '-1') @@ -100,6 +101,7 @@ flag_set_filter = SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) splits_repository = SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) impressions_repository = SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) + rule_based_segments_repository = SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) runtime_producer = SplitIoClient::Telemetry::RuntimeProducer.new(config) events_repository = SplitIoClient::Cache::Repositories::EventsRepository.new(config, 'sdk_key', runtime_producer) impressions_counter = SplitIoClient::Engine::Common::ImpressionCounter.new @@ -107,13 +109,13 @@ unique_keys_tracker = SplitIoClient::Engine::Impressions::UniqueKeysTracker.new(config, filter_adapter, nil, Concurrent::Hash.new) impression_manager = SplitIoClient::Engine::Common::ImpressionManager.new(config, impressions_repository, impressions_counter, runtime_producer, SplitIoClient::Observers::ImpressionObserver.new, unique_keys_tracker) evaluation_producer = SplitIoClient::Telemetry::EvaluationProducer.new(config) - evaluator = SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) + evaluator = SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, rule_based_segments_repository, config) split_client = SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) splits = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json')) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][0]], [], -1) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][1]], [], -1) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][2]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][0]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][1]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][2]], [], -1) expect(split_client.get_treatment('key1', 'with_track_disabled')).to eq('off') expect(split_client.get_treatment('key2', 'with_track_enabled')).to eq('off') @@ -139,6 +141,7 @@ flag_set_filter = SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) splits_repository = SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) impressions_repository = SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) + rule_based_segments_repository = SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) runtime_producer = SplitIoClient::Telemetry::RuntimeProducer.new(config) events_repository = SplitIoClient::Cache::Repositories::EventsRepository.new(config, 'sdk_key', runtime_producer) impressions_counter = SplitIoClient::Engine::Common::ImpressionCounter.new @@ -146,13 +149,13 @@ unique_keys_tracker = SplitIoClient::Engine::Impressions::UniqueKeysTracker.new(config, filter_adapter, nil, Concurrent::Hash.new) impression_manager = SplitIoClient::Engine::Common::ImpressionManager.new(config, impressions_repository, impressions_counter, runtime_producer, SplitIoClient::Observers::ImpressionObserver.new, unique_keys_tracker) evaluation_producer = SplitIoClient::Telemetry::EvaluationProducer.new(config) - evaluator = SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) + evaluator = SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, rule_based_segments_repository, config) split_client = SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) splits = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json')) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][0]], [], -1) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][1]], [], -1) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][2]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][0]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][1]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][2]], [], -1) expect(split_client.get_treatment('key1', 'with_track_disabled')).to eq('off') expect(split_client.get_treatment('key2', 'with_track_enabled')).to eq('off') @@ -178,6 +181,7 @@ flag_set_filter = SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) splits_repository = SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) impressions_repository = SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) + rule_based_segments_repository = SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) runtime_producer = SplitIoClient::Telemetry::RuntimeProducer.new(config) events_repository = SplitIoClient::Cache::Repositories::EventsRepository.new(config, 'sdk_key', runtime_producer) impressions_counter = SplitIoClient::Engine::Common::ImpressionCounter.new @@ -185,13 +189,13 @@ unique_keys_tracker = SplitIoClient::Engine::Impressions::UniqueKeysTracker.new(config, filter_adapter, nil, Concurrent::Hash.new) impression_manager = SplitIoClient::Engine::Common::ImpressionManager.new(config, impressions_repository, impressions_counter, runtime_producer, SplitIoClient::Observers::ImpressionObserver.new, unique_keys_tracker) evaluation_producer = SplitIoClient::Telemetry::EvaluationProducer.new(config) - evaluator = SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) + evaluator = SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, rule_based_segments_repository, config) split_client = SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) splits = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/imp-toggle.json')) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][0]], [], -1) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][1]], [], -1) - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][2]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][0]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][1]], [], -1) + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:ff][:d][2]], [], -1) expect(split_client.get_treatment('key1', 'with_track_disabled')).to eq('off') expect(split_client.get_treatment('key2', 'with_track_enabled')).to eq('off') diff --git a/spec/splitclient/split_factory_spec.rb b/spec/splitclient/split_factory_spec.rb index 5cfec28c..dd0ef73a 100644 --- a/spec/splitclient/split_factory_spec.rb +++ b/spec/splitclient/split_factory_spec.rb @@ -69,7 +69,7 @@ let(:mode) { :standalone } it 'log an error stating Api Key is invalid' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -89,7 +89,7 @@ let(:mode) { :standalone } it 'log an error stating Api Key is invalid' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -112,9 +112,9 @@ end it 'log an error stating Api Key is invalid' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits_with_segments_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473863097220') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1473863097220&rbSince=-1') .to_return(status: 200, body: []) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1') .to_return(status: 403, body: []) @@ -140,7 +140,7 @@ let(:mode) { :standalone } it 'log an error' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') @@ -174,7 +174,7 @@ end it 'logs warnings stating number of factories' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) described_class.new('API_KEY', options) @@ -188,7 +188,7 @@ end it 'decreases number of registered factories on client destroy' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) expect(SplitIoClient.split_factory_registry.number_of_factories_for('API_KEY')).to eq 0 @@ -203,7 +203,7 @@ end it 'active and redundant factories' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') @@ -239,7 +239,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -260,7 +260,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -281,7 +281,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -302,7 +302,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') diff --git a/spec/splitclient/split_manager_spec.rb b/spec/splitclient/split_manager_spec.rb index 4714a40f..0f9bdd0e 100644 --- a/spec/splitclient/split_manager_spec.rb +++ b/spec/splitclient/split_manager_spec.rb @@ -10,7 +10,7 @@ let(:segments) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/segments/engine_segments.json'))) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/demo?since=-1') @@ -25,7 +25,7 @@ stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1473413807667&rbSince=-1") .to_return(status: 200, body: "", headers: {}) end @@ -85,7 +85,7 @@ context '#splits' do it 'returns empty array and logs error when not ready' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=-1") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=-1") .to_return(status: 200, body: "", headers: {}) allow(subject).to receive(:ready?).and_return(false) @@ -109,10 +109,10 @@ let(:splits3) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/splits/splits3.json'))) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits3) - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1473863097220") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since=1473863097220&rbSince=-1") .to_return(status: 200, body: "", headers: {}) end @@ -137,10 +137,10 @@ let(:splits4) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/splits/splits4.json'))) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits4) - stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.3&since") .to_return(status: 200, body: "", headers: {}) end diff --git a/spec/splitclient_rb_corner_cases_spec.rb b/spec/splitclient_rb_corner_cases_spec.rb index b5d763ea..c4346f85 100644 --- a/spec/splitclient_rb_corner_cases_spec.rb +++ b/spec/splitclient_rb_corner_cases_spec.rb @@ -21,10 +21,10 @@ before do stub_request(:post, 'https://events.split.io/api/testImpressions/bulk').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 200, body: splits_json) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1').to_return(status: 200, body: splits_json) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/demo?since=-1').to_return(status: 200, body: segment_res) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1').to_return(status: 200, body: segment_res) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667').to_return(status: 200, body: segment_res) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=1473413807667&rbSince=-1').to_return(status: 200, body: segment_res) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: segment_res) stub_request(:post, 'https://events.split.io/api/testImpressions/count').to_return(status: 200, body: '') end diff --git a/spec/test_data/rule_based_segments/rule_base_segments.json b/spec/test_data/rule_based_segments/rule_base_segments.json new file mode 100644 index 00000000..deafbdc2 --- /dev/null +++ b/spec/test_data/rule_based_segments/rule_base_segments.json @@ -0,0 +1,135 @@ +{"ff": {"d": [ + { + "changeNumber": 10, + "trafficTypeName": "user", + "name": "rbs_feature_flag", + "trafficAllocation": 100, + "trafficAllocationSeed": 1828377380, + "seed": -286617921, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "algo": 2, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "IN_RULE_BASED_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "sample_rule_based_segment" + } + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "in rule based segment sample_rule_based_segment" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "ALL_KEYS", + "negate": false + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ], + "configurations": {}, + "sets": [], + "impressionsDisabled": false + } + ], "t": 1506703262916, "s": -1}, +"rbs": {"t": 1506703262916, "s": -1, "d": + [{ + "changeNumber": 5, + "name": "dependent_rbs", + "status": "ACTIVE", + "trafficTypeName": "user", + "excluded":{"keys":["mauro@split.io","gaston@split.io"],"segments":[]}, + "conditions": [ + { + "conditionType": "WHITELIST", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": "email" + }, + "matcherType": "ENDS_WITH", + "negate": false, + "whitelistMatcherData": { + "whitelist": [ + "@split.io" + ] + } + } + ] + } + } + ]}, + { + "changeNumber": 5, + "name": "sample_rule_based_segment", + "status": "ACTIVE", + "trafficTypeName": "user", + "excluded": { + "keys": [], + "segments": [] + }, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "IN_RULE_BASED_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "dependent_rbs" + } + } + ] + } + } + ] + }] +}} diff --git a/spec/test_data/rule_based_segments/rule_base_segments2.json b/spec/test_data/rule_based_segments/rule_base_segments2.json new file mode 100644 index 00000000..f0ab0e1e --- /dev/null +++ b/spec/test_data/rule_based_segments/rule_base_segments2.json @@ -0,0 +1,140 @@ +{"ff": {"d": [ + { + "changeNumber": 10, + "trafficTypeName": "user", + "name": "rbs_feature_flag", + "trafficAllocation": 100, + "trafficAllocationSeed": 1828377380, + "seed": -286617921, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "algo": 2, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "IN_RULE_BASED_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "sample_rule_based_segment" + } + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "in rule based segment sample_rule_based_segment" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "ALL_KEYS", + "negate": false + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ], + "configurations": {}, + "sets": [], + "impressionsDisabled": false + } +], "t": 1506703262916, "s": -1}, +"rbs": {"t": 1506703262916, "s": -1, "d": [ + { + "changeNumber": 5, + "name": "sample_rule_based_segment", + "status": "ACTIVE", + "trafficTypeName": "user", + "excluded":{ + "keys":["mauro@split.io","gaston@split.io"], + "segments":[{"type":"rule-based", "name":"no_excludes"}] + }, + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": "email" + }, + "matcherType": "START_WITH", + "negate": false, + "whitelistMatcherData": { + "whitelist": [ + "bilal" + ] + } + } + ] + } + } + ] + }, + { + "changeNumber": 5, + "name": "no_excludes", + "status": "ACTIVE", + "trafficTypeName": "user", + "excluded":{ + "keys":["bilal2@split.io"], + "segments":[] + }, + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": "email" + }, + "matcherType": "ENDS_WITH", + "negate": false, + "whitelistMatcherData": { + "whitelist": [ + "@split.io" + ] + } + } + ] + } + } + ] + } +]}} diff --git a/spec/test_data/rule_based_segments/rule_base_segments3.json b/spec/test_data/rule_based_segments/rule_base_segments3.json new file mode 100644 index 00000000..fa7af16f --- /dev/null +++ b/spec/test_data/rule_based_segments/rule_base_segments3.json @@ -0,0 +1,108 @@ +{"ff": {"d": [ + { + "changeNumber": 10, + "trafficTypeName": "user", + "name": "rbs_feature_flag", + "trafficAllocation": 100, + "trafficAllocationSeed": 1828377380, + "seed": -286617921, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "algo": 2, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "IN_RULE_BASED_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "sample_rule_based_segment" + } + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "in rule based segment sample_rule_based_segment" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "ALL_KEYS", + "negate": false + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ], + "configurations": {}, + "sets": [], + "impressionsDisabled": false + } +], "t": 1506703262916, "s": -1}, +"rbs": {"t": 1506703262916, "s": -1, "d": [ + { + "changeNumber": 5, + "name": "sample_rule_based_segment", + "status": "ACTIVE", + "trafficTypeName": "user", + "excluded":{ + "keys":["mauro@split.io","gaston@split.io"], + "segments":[{"type":"standard", "name":"segment1"}] + }, + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": "email" + }, + "matcherType": "ENDS_WITH", + "negate": false, + "whitelistMatcherData": { + "whitelist": [ + "@split.io" + ] + } + } + ] + } + } + ] + } +]}} diff --git a/spec/test_data/rule_based_segments/split_old_spec.json b/spec/test_data/rule_based_segments/split_old_spec.json new file mode 100644 index 00000000..0d7edf86 --- /dev/null +++ b/spec/test_data/rule_based_segments/split_old_spec.json @@ -0,0 +1,328 @@ +{ + "splits": [ + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "whitelist_feature", + "seed": -1222652054, + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "WHITELIST", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": { + "whitelist": [ + "whitelisted_user" + ] + } + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + } + ] + }, + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ] + } + ], + "sets": ["set1", "set2"] + }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "all_feature", + "seed": 1699838640, + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ] + } + ], + "sets": ["set4"] + }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "killed_feature", + "seed": -480091424, + "status": "ACTIVE", + "killed": true, + "changeNumber": 123, + "defaultTreatment": "defTreatment", + "configurations": { + "off": "{\"size\":15,\"test\":20}", + "defTreatment": "{\"size\":15,\"defTreatment\":true}" + }, + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "defTreatment", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ] + } + ], + "sets": ["set3"] + }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "sample_feature", + "seed": 1548363147, + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "defaultTreatment": "off", + "configurations": { + "on": "{\"size\":15,\"test\":20}" + }, + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "employees" + }, + "whitelistMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + } + ] + }, + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "human_beigns" + }, + "whitelistMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 30 + }, + { + "treatment": "off", + "size": 70 + } + ] + } + ], + "sets": ["set1"] + }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "dependency_test", + "seed": 1222652054, + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "IN_SPLIT_TREATMENT", + "negate": false, + "userDefinedSegmentMatcherData": null, + "dependencyMatcherData": { + "split": "all_feature", + "treatments": ["on"] + } + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ] + } + ], + "sets": [] + }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "regex_test", + "seed": 1222652051, + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "MATCHES_STRING", + "negate": false, + "userDefinedSegmentMatcherData": null, + "stringMatcherData": "abc[0-9]" + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ] + } + ], + "sets": [] + }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "boolean_test", + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "seed": 12321809, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "EQUAL_TO_BOOLEAN", + "negate": false, + "userDefinedSegmentMatcherData": null, + "booleanMatcherData": true + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ] + } + ], + "sets": [] + } + ], + "since": -1, + "till": 1457726098069 +} \ No newline at end of file diff --git a/spec/test_data/splits/between_matcher/datetime_matcher_splits.json b/spec/test_data/splits/between_matcher/datetime_matcher_splits.json index d1e3b3df..73e7ffe2 100644 --- a/spec/test_data/splits/between_matcher/datetime_matcher_splits.json +++ b/spec/test_data/splits/between_matcher/datetime_matcher_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -50,5 +50,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/between_matcher/negate_number_matcher_splits.json b/spec/test_data/splits/between_matcher/negate_number_matcher_splits.json index 46d8bab1..9d93d964 100644 --- a/spec/test_data/splits/between_matcher/negate_number_matcher_splits.json +++ b/spec/test_data/splits/between_matcher/negate_number_matcher_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -50,5 +50,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/between_matcher/negative_number_matcher_splits.json b/spec/test_data/splits/between_matcher/negative_number_matcher_splits.json index 64f4182f..105ca471 100644 --- a/spec/test_data/splits/between_matcher/negative_number_matcher_splits.json +++ b/spec/test_data/splits/between_matcher/negative_number_matcher_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -50,5 +50,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/between_matcher/number_matcher_splits.json b/spec/test_data/splits/between_matcher/number_matcher_splits.json index bef6b87a..f5e98ff0 100644 --- a/spec/test_data/splits/between_matcher/number_matcher_splits.json +++ b/spec/test_data/splits/between_matcher/number_matcher_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -50,5 +50,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/boolean_matcher/splits.json b/spec/test_data/splits/boolean_matcher/splits.json index 6cfd69e7..9f81228e 100644 --- a/spec/test_data/splits/boolean_matcher/splits.json +++ b/spec/test_data/splits/boolean_matcher/splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -46,5 +46,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/combining_matcher_splits.json b/spec/test_data/splits/combining_matcher_splits.json index fc2ddcc1..86c258ea 100644 --- a/spec/test_data/splits/combining_matcher_splits.json +++ b/spec/test_data/splits/combining_matcher_splits.json @@ -1,5 +1,6 @@ +{ "ff":{ + "d": [ { - "splits": [{ "trafficTypeName": "user", "name": "PASSENGER_anding", "trafficAllocation": 100, @@ -111,5 +112,6 @@ }], "label": "in segment employees" }] - }] + }],"s":-1, "t":-1}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/engine/all_keys_matcher.json b/spec/test_data/splits/engine/all_keys_matcher.json index 107e5e2d..70c425f8 100644 --- a/spec/test_data/splits/engine/all_keys_matcher.json +++ b/spec/test_data/splits/engine/all_keys_matcher.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -36,5 +36,8 @@ ], "sets": ["set_1"] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/configurations.json b/spec/test_data/splits/engine/configurations.json index 05ccef7a..edaecd8d 100644 --- a/spec/test_data/splits/engine/configurations.json +++ b/spec/test_data/splits/engine/configurations.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -172,5 +172,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/dependency_matcher.json b/spec/test_data/splits/engine/dependency_matcher.json index 5a85fa41..ba4f1c4d 100644 --- a/spec/test_data/splits/engine/dependency_matcher.json +++ b/spec/test_data/splits/engine/dependency_matcher.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -73,5 +73,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/equal_to_set_matcher.json b/spec/test_data/splits/engine/equal_to_set_matcher.json index b7c07f23..83f7cc6e 100644 --- a/spec/test_data/splits/engine/equal_to_set_matcher.json +++ b/spec/test_data/splits/engine/equal_to_set_matcher.json @@ -1,5 +1,5 @@ -{ - "splits":[ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "mauro_test", @@ -119,5 +119,8 @@ ], "sets": ["set_2"] } - ] -} \ No newline at end of file + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} +} diff --git a/spec/test_data/splits/engine/impressions_test.json b/spec/test_data/splits/engine/impressions_test.json index c4743e68..79c1524c 100644 --- a/spec/test_data/splits/engine/impressions_test.json +++ b/spec/test_data/splits/engine/impressions_test.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -85,5 +85,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/killed.json b/spec/test_data/splits/engine/killed.json index 2a0315cf..be6f02ba 100644 --- a/spec/test_data/splits/engine/killed.json +++ b/spec/test_data/splits/engine/killed.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -32,5 +32,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/segment_deleted_matcher.json b/spec/test_data/splits/engine/segment_deleted_matcher.json index a558e5f0..e7816f47 100644 --- a/spec/test_data/splits/engine/segment_deleted_matcher.json +++ b/spec/test_data/splits/engine/segment_deleted_matcher.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -38,5 +38,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/segment_matcher.json b/spec/test_data/splits/engine/segment_matcher.json index 079049d2..9c7980f1 100644 --- a/spec/test_data/splits/engine/segment_matcher.json +++ b/spec/test_data/splits/engine/segment_matcher.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -39,5 +39,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/segment_matcher2.json b/spec/test_data/splits/engine/segment_matcher2.json index 62737bbe..d5e25dfc 100644 --- a/spec/test_data/splits/engine/segment_matcher2.json +++ b/spec/test_data/splits/engine/segment_matcher2.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -117,5 +117,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/engine/whitelist_matcher.json b/spec/test_data/splits/engine/whitelist_matcher.json index c9e756ad..1c491172 100644 --- a/spec/test_data/splits/engine/whitelist_matcher.json +++ b/spec/test_data/splits/engine/whitelist_matcher.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -37,5 +37,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/equal_to_matcher/date_splits.json b/spec/test_data/splits/equal_to_matcher/date_splits.json index fa5fa89b..5267517b 100644 --- a/spec/test_data/splits/equal_to_matcher/date_splits.json +++ b/spec/test_data/splits/equal_to_matcher/date_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -46,5 +46,8 @@ ], "sets": ["set_1"] } - ] + ], + "s": -1, + "t": -1}, + "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/equal_to_matcher/negative_splits.json b/spec/test_data/splits/equal_to_matcher/negative_splits.json index 84f5fc33..548bcee8 100644 --- a/spec/test_data/splits/equal_to_matcher/negative_splits.json +++ b/spec/test_data/splits/equal_to_matcher/negative_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -46,5 +46,8 @@ ], "sets": ["set_1"] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/equal_to_matcher/splits.json b/spec/test_data/splits/equal_to_matcher/splits.json index 13f2cae6..5f603999 100644 --- a/spec/test_data/splits/equal_to_matcher/splits.json +++ b/spec/test_data/splits/equal_to_matcher/splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -46,5 +46,8 @@ ], "sets": ["set_1"] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/equal_to_matcher/zero_splits.json b/spec/test_data/splits/equal_to_matcher/zero_splits.json index 17c63578..da231d90 100644 --- a/spec/test_data/splits/equal_to_matcher/zero_splits.json +++ b/spec/test_data/splits/equal_to_matcher/zero_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -46,5 +46,8 @@ ], "sets": ["set_1"] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/greater_than_or_equal_to_matcher/date_splits.json b/spec/test_data/splits/greater_than_or_equal_to_matcher/date_splits.json index 59f29335..643e07a9 100644 --- a/spec/test_data/splits/greater_than_or_equal_to_matcher/date_splits.json +++ b/spec/test_data/splits/greater_than_or_equal_to_matcher/date_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -45,5 +45,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/greater_than_or_equal_to_matcher/negative_splits.json b/spec/test_data/splits/greater_than_or_equal_to_matcher/negative_splits.json index 755948b3..0d5ccde7 100644 --- a/spec/test_data/splits/greater_than_or_equal_to_matcher/negative_splits.json +++ b/spec/test_data/splits/greater_than_or_equal_to_matcher/negative_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -45,5 +45,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/greater_than_or_equal_to_matcher/splits.json b/spec/test_data/splits/greater_than_or_equal_to_matcher/splits.json index e8a7f72f..730aa286 100644 --- a/spec/test_data/splits/greater_than_or_equal_to_matcher/splits.json +++ b/spec/test_data/splits/greater_than_or_equal_to_matcher/splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -45,5 +45,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/imp-toggle.json b/spec/test_data/splits/imp-toggle.json index 77d7a4e9..b70d6684 100644 --- a/spec/test_data/splits/imp-toggle.json +++ b/spec/test_data/splits/imp-toggle.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "with_track_disabled", @@ -152,4 +152,6 @@ ], "since": -1, "till": 1675259356568 + }, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits.json b/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits.json index 6faf61c3..0f74fa5b 100644 --- a/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits.json +++ b/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -45,5 +45,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits2.json b/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits2.json index 7630b564..eab2e7e2 100644 --- a/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits2.json +++ b/spec/test_data/splits/less_than_or_equal_to_matcher/date_splits2.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":null, "environment":null, @@ -49,5 +49,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/less_than_or_equal_to_matcher/negative_splits.json b/spec/test_data/splits/less_than_or_equal_to_matcher/negative_splits.json index ca725e3c..db1a51f5 100644 --- a/spec/test_data/splits/less_than_or_equal_to_matcher/negative_splits.json +++ b/spec/test_data/splits/less_than_or_equal_to_matcher/negative_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -45,5 +45,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/less_than_or_equal_to_matcher/splits.json b/spec/test_data/splits/less_than_or_equal_to_matcher/splits.json index 76850210..cc2e6dc3 100644 --- a/spec/test_data/splits/less_than_or_equal_to_matcher/splits.json +++ b/spec/test_data/splits/less_than_or_equal_to_matcher/splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -45,5 +45,8 @@ } ] } - ] + ], + "s": -1, + "t": -1 +}, "rbs": {"d":[], "s":-1, "t": -1} } diff --git a/spec/test_data/splits/semver_matchers/semver_between.json b/spec/test_data/splits/semver_matchers/semver_between.json index 44edc2b6..9a0a3c7b 100644 --- a/spec/test_data/splits/semver_matchers/semver_between.json +++ b/spec/test_data/splits/semver_matchers/semver_between.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "semver_between", @@ -82,5 +82,6 @@ } ], "since": -1, - "till": 1675259356568 + "till": 1675259356568}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/semver_matchers/semver_equalto.json b/spec/test_data/splits/semver_matchers/semver_equalto.json index c3daa9ea..e7699e16 100644 --- a/spec/test_data/splits/semver_matchers/semver_equalto.json +++ b/spec/test_data/splits/semver_matchers/semver_equalto.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "semver_equalto", @@ -81,5 +81,6 @@ } ], "since": -1, - "till": 1675259356568 + "till": 1675259356568}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json b/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json index 40f0f036..1fde9c28 100644 --- a/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json +++ b/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "semver_greater_or_equalto", @@ -81,5 +81,6 @@ } ], "since": -1, - "till": 1675259356568 + "till": 1675259356568}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/semver_matchers/semver_inlist.json b/spec/test_data/splits/semver_matchers/semver_inlist.json index 9f1e6246..8feafc58 100644 --- a/spec/test_data/splits/semver_matchers/semver_inlist.json +++ b/spec/test_data/splits/semver_matchers/semver_inlist.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "semver_inlist", @@ -82,5 +82,6 @@ } ], "since": -1, - "till": 1675259356568 + "till": 1675259356568}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json b/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json index 9a46807f..6704a6c3 100644 --- a/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json +++ b/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "user", "name": "semver_less_or_equalto", @@ -81,5 +81,6 @@ } ], "since": -1, - "till": 1675259356568 + "till": 1675259356568}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/splits4.json b/spec/test_data/splits/splits4.json index 17f0ec88..f9d3f993 100644 --- a/spec/test_data/splits/splits4.json +++ b/spec/test_data/splits/splits4.json @@ -1,5 +1,6 @@ -{ - "splits": [{ +{"ff": { + "d":[ + { "trafficTypeName": "user", "name": "uber_feature", "trafficAllocation": 100, @@ -83,4 +84,6 @@ "label": "category in list [expert] and last_ride on or after 2017-07-27 01:18AM" }] } -]} +] +}, "rbs": {"d":[], "s":-1, "t":-1} +} diff --git a/spec/test_data/splits/splits_traffic_allocation.json b/spec/test_data/splits/splits_traffic_allocation.json index ce35c5e9..e1a58647 100644 --- a/spec/test_data/splits/splits_traffic_allocation.json +++ b/spec/test_data/splits/splits_traffic_allocation.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "trafficTypeName": "account", "name": "Traffic_Allocation_UI", @@ -355,4 +355,5 @@ ], "since": -1, "till": 1470855828956 +}, "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/splits_traffic_allocation_one_percent.json b/spec/test_data/splits/splits_traffic_allocation_one_percent.json index 5b523c21..d480a521 100644 --- a/spec/test_data/splits/splits_traffic_allocation_one_percent.json +++ b/spec/test_data/splits/splits_traffic_allocation_one_percent.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "name": "Traffic_Allocation_One_Percent", "algo": 1, @@ -37,5 +37,6 @@ } ] } - ] + ], "s":-1, "t":-1}, + "rbs": {"d":[], "s":-1, "t":-1} } diff --git a/spec/test_data/splits/whitelist_matcher_splits.json b/spec/test_data/splits/whitelist_matcher_splits.json index 1a517656..81259de9 100644 --- a/spec/test_data/splits/whitelist_matcher_splits.json +++ b/spec/test_data/splits/whitelist_matcher_splits.json @@ -1,5 +1,5 @@ -{ - "splits": [ +{ "ff":{ + "d": [ { "orgId":"cee838c0-b3eb-11e5-855f-4eacec19f7bf", "environment":"cf2d09f0-b3eb-11e5-855f-4eacec19f7bf", @@ -52,5 +52,6 @@ } ] } - ] + ], "s":-1, "t":-1}, + "rbs": {"d":[], "s":-1, "t":-1} } From 61e502f817c62e113dfc541380569819780d4dc8 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Wed, 14 May 2025 21:12:00 -0700 Subject: [PATCH 02/11] Added old spec support --- .../cache/fetchers/split_fetcher.rb | 4 +- lib/splitclient-rb/engine/api/client.rb | 3 + lib/splitclient-rb/engine/api/splits.rb | 59 +++++++++++++++-- .../helpers/repository_helper.rb | 7 +- lib/splitclient-rb/split_config.rb | 4 ++ .../sse/workers/splits_worker.rb | 4 +- spec/engine/api/splits_spec.rb | 51 ++++++++++++++- spec/integrations/old_spec_client_spec.rb | 42 ++++++++++++ .../rule_based_segments/split_old_spec.json | 64 ------------------- 9 files changed, 163 insertions(+), 75 deletions(-) create mode 100644 spec/integrations/old_spec_client_spec.rb diff --git a/lib/splitclient-rb/cache/fetchers/split_fetcher.rb b/lib/splitclient-rb/cache/fetchers/split_fetcher.rb index c2772d62..cfa0b636 100644 --- a/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +++ b/lib/splitclient-rb/cache/fetchers/split_fetcher.rb @@ -25,8 +25,8 @@ def call def fetch_splits(fetch_options = { cache_control_headers: false, till: nil }) @semaphore.synchronize do data = splits_since(@splits_repository.get_change_number, @rule_based_segments_repository.get_change_number, fetch_options) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@splits_repository, data[:ff][:d], data[:ff][:t], @config) - SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segments_repository, data[:rbs][:d], data[:rbs][:t], @config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@splits_repository, data[:ff][:d], data[:ff][:t], @config, @splits_api.clear_storage) + SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segments_repository, data[:rbs][:d], data[:rbs][:t], @config, @splits_api.clear_storage) @splits_repository.set_segment_names(data[:segment_names]) @rule_based_segments_repository.set_segment_names(data[:segment_names]) @config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled diff --git a/lib/splitclient-rb/engine/api/client.rb b/lib/splitclient-rb/engine/api/client.rb index 65dcd027..d9d6e0df 100644 --- a/lib/splitclient-rb/engine/api/client.rb +++ b/lib/splitclient-rb/engine/api/client.rb @@ -50,6 +50,9 @@ def post_api(url, api_key, data, headers = {}, params = {}) raise e, 'Split SDK failed to connect to backend to post information', e.backtrace end + def sdk_url_overriden? + @config.sdk_url_overriden? + end private def api_client diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index 0596c9de..45c1b30f 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -5,28 +5,68 @@ module Api # Retrieves split definitions from the Split Backend class Splits < Client + PROXY_CHECK_INTERVAL_SECONDS = 24 * 60 * 60 + SPEC_1_1 = "1.1" + def initialize(api_key, config, telemetry_runtime_producer) super(config) @api_key = api_key @telemetry_runtime_producer = telemetry_runtime_producer @flag_sets_filter = @config.flag_sets_filter + @spec_version = SplitIoClient::Spec::FeatureFlags::SPEC_VERSION + @last_proxy_check_timestamp = 0 + @clear_storage = false end def since(since, since_rbs, fetch_options = { cache_control_headers: false, till: nil, sets: nil}) start = Time.now + + if check_last_proxy_check_timestamp + puts "switching to new spec" + @spec_version = SplitIoClient::Spec::FeatureFlags::SPEC_VERSION + @config.logger.debug("Switching to new Feature flag spec #{@spec_version} and fetching.") + since = -1 + since_rbs = -1 + fetch_options = { cache_control_headers: false, till: nil, sets: nil} + end + + if @spec_version == Splits::SPEC_1_1 + params = { s: @spec_version, since: since } + else + params = { s: @spec_version, since: since, rbSince: since_rbs } + end - params = { s: SplitIoClient::Spec::FeatureFlags::SPEC_VERSION, since: since, rbSince: since_rbs } params[:sets] = @flag_sets_filter.join(",") unless @flag_sets_filter.empty? params[:till] = fetch_options[:till] unless fetch_options[:till].nil? @config.logger.debug("Fetching from splitChanges with #{params}: ") response = get_api("#{@config.base_uri}/splitChanges", @api_key, params, fetch_options[:cache_control_headers]) + if response.status == 414 @config.logger.error("Error fetching feature flags; the amount of flag sets provided are too big, causing uri length error.") raise ApiException.new response.body, 414 end + + if response.status == 400 and sdk_url_overriden? and @spec_version == SplitIoClient::Spec::FeatureFlags::SPEC_VERSION + @config.logger.warn("Detected proxy response error, changing spec version from #{@spec_version} to #{Splits::SPEC_1_1} and re-fetching.") + @spec_version = Splits::SPEC_1_1 + @last_proxy_check_timestamp = Time.now + return since(since, 0, fetch_options = {cache_control_headers: fetch_options[:cache_control_headers], till: fetch_options[:till], + sets: fetch_options[:sets]}) + end + if response.success? - result = objects_with_segment_names(response.body) + result = JSON.parse(response.body, symbolize_names: true) + if @spec_version == Splits::SPEC_1_1 + result = convert_to_newSPEC(result) + end + + result = objects_with_segment_names(result) + if @spec_version == SplitIoClient::Spec::FeatureFlags::SPEC_VERSION + @clear_storage = @last_proxy_check_timestamp != 0 + @last_proxy_check_timestamp = 0 + end + unless result[:ff][:d].empty? @config.split_logger.log_if_debug("#{result[:ff][:d].length} feature flags retrieved. since=#{since}") end @@ -52,10 +92,13 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till end end + def clear_storage + @clear_storage + end + private - def objects_with_segment_names(objects_json) - parsed_objects = JSON.parse(objects_json, symbolize_names: true) + def objects_with_segment_names(parsed_objects) parsed_objects[:segment_names] = Set.new parsed_objects[:segment_names] = parsed_objects[:ff][:d].each_with_object(Set.new) do |split, splits| @@ -76,6 +119,14 @@ def objects_with_segment_names(objects_json) parsed_objects end + + def check_last_proxy_check_timestamp + @spec_version == Splits::SPEC_1_1 and ((Time.now - @last_proxy_check_timestamp) >= Splits::PROXY_CHECK_INTERVAL_SECONDS) + end + + def convert_to_newSPEC(body) + {:ff => {:d => body[:splits], :s => body[:since], :t => body[:till]}, :rbs => {:d => [], :s => -1, :t => -1}} + end end end end diff --git a/lib/splitclient-rb/helpers/repository_helper.rb b/lib/splitclient-rb/helpers/repository_helper.rb index 24fdd76b..be0e63c8 100644 --- a/lib/splitclient-rb/helpers/repository_helper.rb +++ b/lib/splitclient-rb/helpers/repository_helper.rb @@ -3,7 +3,7 @@ module SplitIoClient module Helpers class RepositoryHelper - def self.update_feature_flag_repository(feature_flag_repository, feature_flags, change_number, config) + def self.update_feature_flag_repository(feature_flag_repository, feature_flags, change_number, config, clear_storage) to_add = [] to_delete = [] feature_flags.each do |feature_flag| @@ -23,10 +23,11 @@ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, config.logger.debug("storing feature flag (#{feature_flag[:name]})") if config.debug_enabled to_add.push(feature_flag) end + feature_flag_repository.clear if clear_storage feature_flag_repository.update(to_add, to_delete, change_number) end - def self.update_rule_based_segment_repository(rule_based_segment_repository, rule_based_segments, change_number, config) + def self.update_rule_based_segment_repository(rule_based_segment_repository, rule_based_segments, change_number, config, clear_storage) to_add = [] to_delete = [] rule_based_segments.each do |rule_based_segment| @@ -39,6 +40,8 @@ def self.update_rule_based_segment_repository(rule_based_segment_repository, rul config.logger.debug("storing rule based segment (#{rule_based_segment[:name]})") if config.debug_enabled to_add.push(rule_based_segment) end + rule_based_segment_repository.clear if clear_storage + rule_based_segment_repository.update(to_add, to_delete, change_number) end end diff --git a/lib/splitclient-rb/split_config.rb b/lib/splitclient-rb/split_config.rb index da434c91..de7f3e4d 100644 --- a/lib/splitclient-rb/split_config.rb +++ b/lib/splitclient-rb/split_config.rb @@ -645,6 +645,10 @@ def consumer? @mode.equal?(:consumer) end + def sdk_url_overriden? + return @base_uri != SplitConfig.default_base_uri + end + # # gets the hostname where the sdk gem is running # diff --git a/lib/splitclient-rb/sse/workers/splits_worker.rb b/lib/splitclient-rb/sse/workers/splits_worker.rb index 419a3814..88b06660 100644 --- a/lib/splitclient-rb/sse/workers/splits_worker.rb +++ b/lib/splitclient-rb/sse/workers/splits_worker.rb @@ -71,7 +71,7 @@ def update_feature_flag(notification) new_split = return_object_from_json(notification) SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@feature_flags_repository, [new_split], - notification.data['changeNumber'], @config) + notification.data['changeNumber'], @config, false) fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, "IN_SEGMENT"), @feature_flags_repository) if fetch_rule_based_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, "IN_RULE_BASED_SEGMENT"), notification.data['changeNumber']) return true @@ -93,7 +93,7 @@ def update_rule_based_segment(notification) new_rb_segment = return_object_from_json(notification) SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segment_repository, [new_rb_segment], - notification.data['changeNumber'], @config) + notification.data['changeNumber'], @config, false) fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_rb_segment, "IN_SEGMENT"), @rule_based_segment_repository) # TODO: enable when telemetry spec is added diff --git a/spec/engine/api/splits_spec.rb b/spec/engine/api/splits_spec.rb index af20bd9a..2d293498 100644 --- a/spec/engine/api/splits_spec.rb +++ b/spec/engine/api/splits_spec.rb @@ -21,7 +21,7 @@ stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.3&since=-1&rbSince=-1') .to_return(status: 200, body: splits) - parsed_splits = splits_api.send(:objects_with_segment_names, splits) + parsed_splits = splits_api.send(:objects_with_segment_names, JSON.parse(splits, symbolize_names: true)) expect(parsed_splits[:segment_names]).to eq(Set.new(%w[demo employees])) end @@ -183,4 +183,53 @@ ) end end + + context 'old spec tests' do + let(:old_spec_splits) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../../test_data/rule_based_segments/split_old_spec.json'))) } + let(:config) do + SplitIoClient::SplitConfig.new( + logger: Logger.new(log), + debug_enabled: true, + transport_debug_enabled: true, + base_uri: "https://proxy-server/api" + ) + end + let(:log) { StringIO.new } + let(:telemetry_runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } + let(:splits_api) { described_class.new('', config, telemetry_runtime_producer) } + + it 'switch to old spec url whith proper conditions' do + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return(status: 400, body: '') + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: old_spec_splits) + + parsed_splits = splits_api.since(-1, -1) + + expect(parsed_splits[:ff][:d].length()).to eq(7) + expect(parsed_splits[:ff][:t]).to eq(1457726098069) + expect(parsed_splits[:ff][:s]).to eq(-1) + expect(parsed_splits[:rbs]).to eq({:d => [], :s => -1, :t => -1}) + expect(splits_api.clear_storage).to eq(false) + end + + it 'check new spec after last proxy timestamp expires' do + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return({status: 400, body: ''}, {status: 200, body: splits}) + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: old_spec_splits) + + parsed_splits = splits_api.since(-1, -1) + expect(parsed_splits[:ff][:d].length()).to eq(7) + expect(splits_api.instance_variable_get(:@spec_version)).to eq(SplitIoClient::Api::Splits::SPEC_1_1) + + SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 + sleep 1 + parsed_splits = splits_api.since(-1, -1) + expect(splits_api.clear_storage).to eq(true) + expect(parsed_splits[:ff][:d].length()).to eq(2) + expect(parsed_splits[:rbs][:d].length()).to eq(1) + expect(splits_api.instance_variable_get(:@spec_version)).to eq(SplitIoClient::Spec::FeatureFlags::SPEC_VERSION) + end + end end diff --git a/spec/integrations/old_spec_client_spec.rb b/spec/integrations/old_spec_client_spec.rb new file mode 100644 index 00000000..7ee2526c --- /dev/null +++ b/spec/integrations/old_spec_client_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SplitIoClient do + context 'old spec tests' do + let(:old_spec_splits) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/rule_based_segments/split_old_spec.json'))) } + + it 'check new spec after last proxy timestamp expires' do + splits_rbs = File.read(File.join(SplitIoClient.root, 'spec/test_data/rule_based_segments/rule_base_segments.json')) + + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return({status: 400, body: ''}, {status: 200, body: splits_rbs}) + stub_request(:get, "https://sdk.split.io/api/splitChanges?rbSince=1506703262916&s=1.3&since=1506703262916") + .to_return(status: 200, body: '') + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: old_spec_splits) + stub_request(:get, "https://proxy-server/api/splitChanges?s=1.1&since=1457726098069") + .to_return(status: 200, body: '') + stub_request(:post, "https://telemetry.split.io/api/v1/metrics/config") + .to_return(status: 200, body: '') + + factory_old_spec = + SplitIoClient::SplitFactory.new('test_api_key', + {impressions_mode: :none, + features_refresh_rate: 2, + base_uri: "https://proxy-server/api", + streaming_enabled: false}) + + SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 + client_old_spec = factory_old_spec.client + client_old_spec.block_until_ready + expect(client_old_spec.get_treatment('whitelisted_user', 'whitelist_feature')).to eq('on') + + sleep 1 + split_fetcher = factory_old_spec.instance_variable_get(:@split_fetcher) + split_fetcher.fetch_splits + sleep 1 + expect(client_old_spec.get_treatment('bilal@split.io', 'rbs_feature_flag', {:email => 'bilal@split.io'})).to eq('on') + end + end +end diff --git a/spec/test_data/rule_based_segments/split_old_spec.json b/spec/test_data/rule_based_segments/split_old_spec.json index 0d7edf86..2d0aef1e 100644 --- a/spec/test_data/rule_based_segments/split_old_spec.json +++ b/spec/test_data/rule_based_segments/split_old_spec.json @@ -141,70 +141,6 @@ ], "sets": ["set3"] }, - { - "orgId": null, - "environment": null, - "trafficTypeId": null, - "trafficTypeName": null, - "name": "sample_feature", - "seed": 1548363147, - "status": "ACTIVE", - "killed": false, - "changeNumber": 123, - "defaultTreatment": "off", - "configurations": { - "on": "{\"size\":15,\"test\":20}" - }, - "conditions": [ - { - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "employees" - }, - "whitelistMatcherData": null - } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 100 - } - ] - }, - { - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "human_beigns" - }, - "whitelistMatcherData": null - } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 30 - }, - { - "treatment": "off", - "size": 70 - } - ] - } - ], - "sets": ["set1"] - }, { "orgId": null, "environment": null, From 2e54131fd0abcad871d1fc7fdf1e9e1f7663a6d9 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 15 May 2025 09:35:03 -0700 Subject: [PATCH 03/11] update tests --- .../cache/fetchers/split_fetcher.rb | 2 +- .../cache/repositories/splits_repository.rb | 4 ++ lib/splitclient-rb/engine/api/splits.rb | 1 - .../helpers/repository_helper.rb | 3 +- .../sse/workers/splits_worker.rb | 2 +- spec/integrations/in_memory_client_spec.rb | 38 +++++++++++++++++ spec/integrations/old_spec_client_spec.rb | 42 ------------------- 7 files changed, 45 insertions(+), 47 deletions(-) delete mode 100644 spec/integrations/old_spec_client_spec.rb diff --git a/lib/splitclient-rb/cache/fetchers/split_fetcher.rb b/lib/splitclient-rb/cache/fetchers/split_fetcher.rb index cfa0b636..c1cba9dc 100644 --- a/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +++ b/lib/splitclient-rb/cache/fetchers/split_fetcher.rb @@ -26,7 +26,7 @@ def fetch_splits(fetch_options = { cache_control_headers: false, till: nil }) @semaphore.synchronize do data = splits_since(@splits_repository.get_change_number, @rule_based_segments_repository.get_change_number, fetch_options) SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@splits_repository, data[:ff][:d], data[:ff][:t], @config, @splits_api.clear_storage) - SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segments_repository, data[:rbs][:d], data[:rbs][:t], @config, @splits_api.clear_storage) + SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segments_repository, data[:rbs][:d], data[:rbs][:t], @config) @splits_repository.set_segment_names(data[:segment_names]) @rule_based_segments_repository.set_segment_names(data[:segment_names]) @config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled diff --git a/lib/splitclient-rb/cache/repositories/splits_repository.rb b/lib/splitclient-rb/cache/repositories/splits_repository.rb index e98e0d84..bc763c36 100644 --- a/lib/splitclient-rb/cache/repositories/splits_repository.rb +++ b/lib/splitclient-rb/cache/repositories/splits_repository.rb @@ -127,6 +127,10 @@ def clear @tt_cache.clear @adapter.clear(namespace_key) + unless @config.mode.equal?(:consumer) + @adapter.set_string(namespace_key('.splits.till'), '-1') + @adapter.initialize_map(namespace_key('.segments.registered')) + end end def kill(change_number, split_name, default_treatment) diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index 45c1b30f..6146d387 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -22,7 +22,6 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till start = Time.now if check_last_proxy_check_timestamp - puts "switching to new spec" @spec_version = SplitIoClient::Spec::FeatureFlags::SPEC_VERSION @config.logger.debug("Switching to new Feature flag spec #{@spec_version} and fetching.") since = -1 diff --git a/lib/splitclient-rb/helpers/repository_helper.rb b/lib/splitclient-rb/helpers/repository_helper.rb index be0e63c8..d66bac33 100644 --- a/lib/splitclient-rb/helpers/repository_helper.rb +++ b/lib/splitclient-rb/helpers/repository_helper.rb @@ -27,7 +27,7 @@ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, feature_flag_repository.update(to_add, to_delete, change_number) end - def self.update_rule_based_segment_repository(rule_based_segment_repository, rule_based_segments, change_number, config, clear_storage) + def self.update_rule_based_segment_repository(rule_based_segment_repository, rule_based_segments, change_number, config) to_add = [] to_delete = [] rule_based_segments.each do |rule_based_segment| @@ -40,7 +40,6 @@ def self.update_rule_based_segment_repository(rule_based_segment_repository, rul config.logger.debug("storing rule based segment (#{rule_based_segment[:name]})") if config.debug_enabled to_add.push(rule_based_segment) end - rule_based_segment_repository.clear if clear_storage rule_based_segment_repository.update(to_add, to_delete, change_number) end diff --git a/lib/splitclient-rb/sse/workers/splits_worker.rb b/lib/splitclient-rb/sse/workers/splits_worker.rb index 88b06660..a6ba1696 100644 --- a/lib/splitclient-rb/sse/workers/splits_worker.rb +++ b/lib/splitclient-rb/sse/workers/splits_worker.rb @@ -93,7 +93,7 @@ def update_rule_based_segment(notification) new_rb_segment = return_object_from_json(notification) SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segment_repository, [new_rb_segment], - notification.data['changeNumber'], @config, false) + notification.data['changeNumber'], @config) fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_rb_segment, "IN_SEGMENT"), @rule_based_segment_repository) # TODO: enable when telemetry spec is added diff --git a/spec/integrations/in_memory_client_spec.rb b/spec/integrations/in_memory_client_spec.rb index ab0538ae..2f2024b2 100644 --- a/spec/integrations/in_memory_client_spec.rb +++ b/spec/integrations/in_memory_client_spec.rb @@ -1381,6 +1381,44 @@ expect(client_rbs.get_treatment('mauro@split.io', 'rbs_feature_flag', {:email => 'mauro@split.io'})).to eq('off') end end + + context 'old spec tests' do + let(:old_spec_splits) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/rule_based_segments/split_old_spec.json'))) } + + it 'check new spec after last proxy timestamp expires' do + splits_rbs = File.read(File.join(SplitIoClient.root, 'spec/test_data/rule_based_segments/rule_base_segments.json')) + + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return({status: 400, body: ''}, {status: 200, body: splits_rbs}) + stub_request(:get, "https://sdk.split.io/api/splitChanges?rbSince=1506703262916&s=1.3&since=1506703262916") + .to_return(status: 200, body: '') + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: old_spec_splits) + stub_request(:get, "https://proxy-server/api/splitChanges?s=1.1&since=1457726098069") + .to_return(status: 200, body: '') + stub_request(:post, "https://telemetry.split.io/api/v1/metrics/config") + .to_return(status: 200, body: '') + + factory_old_spec = + SplitIoClient::SplitFactory.new('test_api_key', + {impressions_mode: :none, + features_refresh_rate: 2, + base_uri: "https://proxy-server/api", + streaming_enabled: false}) + + SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 + client_old_spec = factory_old_spec.client + client_old_spec.block_until_ready + expect(client_old_spec.get_treatment('whitelisted_user', 'whitelist_feature')).to eq('on') + + sleep 1 + split_fetcher = factory_old_spec.instance_variable_get(:@split_fetcher) + split_fetcher.fetch_splits + sleep 1 + expect(client_old_spec.get_treatment('bilal@split.io', 'rbs_feature_flag', {:email => 'bilal@split.io'})).to eq('on') + expect(client_old_spec.get_treatment('whitelisted_user', 'whitelist_feature')).to eq('control') + end + end end private diff --git a/spec/integrations/old_spec_client_spec.rb b/spec/integrations/old_spec_client_spec.rb deleted file mode 100644 index 7ee2526c..00000000 --- a/spec/integrations/old_spec_client_spec.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe SplitIoClient do - context 'old spec tests' do - let(:old_spec_splits) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/rule_based_segments/split_old_spec.json'))) } - - it 'check new spec after last proxy timestamp expires' do - splits_rbs = File.read(File.join(SplitIoClient.root, 'spec/test_data/rule_based_segments/rule_base_segments.json')) - - stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.3&since=-1&rbSince=-1') - .to_return({status: 400, body: ''}, {status: 200, body: splits_rbs}) - stub_request(:get, "https://sdk.split.io/api/splitChanges?rbSince=1506703262916&s=1.3&since=1506703262916") - .to_return(status: 200, body: '') - stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=-1') - .to_return(status: 200, body: old_spec_splits) - stub_request(:get, "https://proxy-server/api/splitChanges?s=1.1&since=1457726098069") - .to_return(status: 200, body: '') - stub_request(:post, "https://telemetry.split.io/api/v1/metrics/config") - .to_return(status: 200, body: '') - - factory_old_spec = - SplitIoClient::SplitFactory.new('test_api_key', - {impressions_mode: :none, - features_refresh_rate: 2, - base_uri: "https://proxy-server/api", - streaming_enabled: false}) - - SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 - client_old_spec = factory_old_spec.client - client_old_spec.block_until_ready - expect(client_old_spec.get_treatment('whitelisted_user', 'whitelist_feature')).to eq('on') - - sleep 1 - split_fetcher = factory_old_spec.instance_variable_get(:@split_fetcher) - split_fetcher.fetch_splits - sleep 1 - expect(client_old_spec.get_treatment('bilal@split.io', 'rbs_feature_flag', {:email => 'bilal@split.io'})).to eq('on') - end - end -end From b7013d49ec2e8fc36f1adc6d8b48a421eca47751 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 15 May 2025 11:49:35 -0700 Subject: [PATCH 04/11] polish --- .../cache/repositories/splits_repository.rb | 17 +++---- lib/splitclient-rb/engine/api/splits.rb | 10 ++++ .../matchers/rule_based_segment_matcher.rb | 46 ++++++++++-------- .../helpers/evaluator_helper.rb | 4 +- .../helpers/repository_helper.rb | 17 ++++--- lib/splitclient-rb/helpers/util.rb | 3 +- .../sse/workers/splits_worker.rb | 48 ++++++++++--------- 7 files changed, 88 insertions(+), 57 deletions(-) diff --git a/lib/splitclient-rb/cache/repositories/splits_repository.rb b/lib/splitclient-rb/cache/repositories/splits_repository.rb index bc763c36..2fa7c396 100644 --- a/lib/splitclient-rb/cache/repositories/splits_repository.rb +++ b/lib/splitclient-rb/cache/repositories/splits_repository.rb @@ -43,10 +43,7 @@ def initialize(config, flag_sets_repository, flag_set_filter) end @flag_sets = flag_sets_repository @flag_set_filter = flag_set_filter - unless @config.mode.equal?(:consumer) - @adapter.set_string(namespace_key('.splits.till'), '-1') - @adapter.initialize_map(namespace_key('.segments.registered')) - end + initialize_keys end def update(to_add, to_delete, new_change_number) @@ -127,10 +124,7 @@ def clear @tt_cache.clear @adapter.clear(namespace_key) - unless @config.mode.equal?(:consumer) - @adapter.set_string(namespace_key('.splits.till'), '-1') - @adapter.initialize_map(namespace_key('.segments.registered')) - end + initialize_keys end def kill(change_number, split_name, default_treatment) @@ -171,6 +165,13 @@ def flag_set_filter private + def initialize_keys + unless @config.mode.equal?(:consumer) + @adapter.set_string(namespace_key('.splits.till'), '-1') + @adapter.initialize_map(namespace_key('.segments.registered')) + end + end + def add_feature_flag(split) return unless split[:name] existing_split = get_split(split[:name]) diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index 6146d387..b8e08974 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -59,6 +59,7 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till result = convert_to_newSPEC(result) end + result[:rbs][:d] = check_rbs_data(result[:rbs][:d]) result = objects_with_segment_names(result) if @spec_version == SplitIoClient::Spec::FeatureFlags::SPEC_VERSION @@ -97,6 +98,15 @@ def clear_storage private + def check_rbs_data(rbs_data) + rbs_data.each do |rb_segment| + rb_segment[:excluded] = {:keys => [], :segments => []} if rb_segment[:excluded].nil? + rb_segment[:excluded][:keys] = [] if rb_segment[:excluded][:keys].nil? + rb_segment[:excluded][:segments] = [] if rb_segment[:excluded][:segments].nil? + end + rbs_data + end + def objects_with_segment_names(parsed_objects) parsed_objects[:segment_names] = Set.new parsed_objects[:segment_names] = diff --git a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb index 69c72272..081c657c 100644 --- a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +++ b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb @@ -25,20 +25,10 @@ def match?(args) rule_based_segment = @rule_based_segments_repository.get_rule_based_segment(@segment_name) return false if rule_based_segment.nil? - if args[:value].nil? or args[:value].empty? - key = args[:matching_key] - else - key = args[:value] - end + key = update_key(args) return false if rule_based_segment[:excluded][:keys].include?(key) - rule_based_segment[:excluded][:segments].each do |segment| - return false if segment[:type] == 'standard' and @segments_repository.in_segment?(segment[:name], key) - - if segment[:type] == 'rule-based' - return false if match_rbs(@rule_based_segments_repository.get_rule_based_segment(segment[:name]), args) - end - end + return false unless check_excluded_segments(rule_based_segment) matches = false rule_based_segment[:conditions].each do |c| @@ -54,13 +44,31 @@ def match?(args) private - def match_rbs(rule_based_segment, args) - rbs_matcher = RuleBasedSegmentMatcher.new(@segments_repository, @rule_based_segments_repository, rule_based_segment[:name], @config) - return rbs_matcher.match?( - matching_key: args[:matching_key], - bucketing_key: args[:value], - attributes: args[:attributes] - ) + def check_excluded_segments(rule_based_segment) + rule_based_segment[:excluded][:segments].each do |segment| + return false if segment[:type] == 'standard' && @segments_repository.in_segment?(segment[:name], key) + + return false if segment[:type] == 'rule-based' && match_rbs( + @rule_based_segments_repository.get_rule_based_segment(segment[:name]), args + ) + end + True + end + + def update_key(args) + if args[:value].nil? || args[:value].empty? + args[:matching_key] + else + args[:value] + end + end + + def match_rbs(rule_based_segment, args) + rbs_matcher = RuleBasedSegmentMatcher.new(@segments_repository, @rule_based_segments_repository, + rule_based_segment[:name], @config) + rbs_matcher.match?(matching_key: args[:matching_key], + bucketing_key: args[:value], + attributes: args[:attributes]) end end end diff --git a/lib/splitclient-rb/helpers/evaluator_helper.rb b/lib/splitclient-rb/helpers/evaluator_helper.rb index 331c7987..2b16e094 100644 --- a/lib/splitclient-rb/helpers/evaluator_helper.rb +++ b/lib/splitclient-rb/helpers/evaluator_helper.rb @@ -8,7 +8,9 @@ def self.matcher_type(condition, segments_repository, rb_segment_repository) segments_repository.adapter.pipelined do condition.matchers.each do |matcher| matchers << if matcher[:negate] - condition.negation_matcher(matcher_instance(matcher[:matcherType], condition, matcher, segments_repository, rb_segment_repository)) + condition.negation_matcher(matcher_instance(matcher[:matcherType], condition, + matcher, segments_repository, + rb_segment_repository)) else matcher_instance(matcher[:matcherType], condition, matcher, segments_repository, rb_segment_repository) end diff --git a/lib/splitclient-rb/helpers/repository_helper.rb b/lib/splitclient-rb/helpers/repository_helper.rb index d66bac33..eb790447 100644 --- a/lib/splitclient-rb/helpers/repository_helper.rb +++ b/lib/splitclient-rb/helpers/repository_helper.rb @@ -13,12 +13,7 @@ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, next end - unless feature_flag.key?(:impressionsDisabled) - feature_flag[:impressionsDisabled] = false - if config.debug_enabled - config.logger.debug("feature flag (#{feature_flag[:name]}) does not have impressionsDisabled field, setting it to false") - end - end + feature_flag = self.check_impressions_disabled(feature_flag, config) config.logger.debug("storing feature flag (#{feature_flag[:name]})") if config.debug_enabled to_add.push(feature_flag) @@ -27,6 +22,16 @@ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, feature_flag_repository.update(to_add, to_delete, change_number) end + def self.check_impressions_disabled(feature_flag, config) + unless feature_flag.key?(:impressionsDisabled) + feature_flag[:impressionsDisabled] = false + if config.debug_enabled + config.logger.debug("feature flag (#{feature_flag[:name]}) does not have impressionsDisabled field, setting it to false") + end + end + feature_flag + end + def self.update_rule_based_segment_repository(rule_based_segment_repository, rule_based_segments, change_number, config) to_add = [] to_delete = [] diff --git a/lib/splitclient-rb/helpers/util.rb b/lib/splitclient-rb/helpers/util.rb index c9b356c4..0f61d0ca 100644 --- a/lib/splitclient-rb/helpers/util.rb +++ b/lib/splitclient-rb/helpers/util.rb @@ -6,7 +6,8 @@ class Util def self.segment_names_by_object(object, matcher_type) object[:conditions].each_with_object(Set.new) do |condition, names| condition[:matcherGroup][:matchers].each do |matcher| - next if matcher[:userDefinedSegmentMatcherData].nil? or matcher[:matcherType] != matcher_type + next if matcher[:userDefinedSegmentMatcherData].nil? || matcher[:matcherType] != matcher_type + names << matcher[:userDefinedSegmentMatcherData][:segmentName] end end diff --git a/lib/splitclient-rb/sse/workers/splits_worker.rb b/lib/splitclient-rb/sse/workers/splits_worker.rb index a6ba1696..27ea916e 100644 --- a/lib/splitclient-rb/sse/workers/splits_worker.rb +++ b/lib/splitclient-rb/sse/workers/splits_worker.rb @@ -4,7 +4,8 @@ module SplitIoClient module SSE module Workers class SplitsWorker - def initialize(synchronizer, config, feature_flags_repository, telemetry_runtime_producer, segment_fetcher, rule_based_segment_repository) + def initialize(synchronizer, config, feature_flags_repository, telemetry_runtime_producer, + segment_fetcher, rule_based_segment_repository) @synchronizer = synchronizer @config = config @feature_flags_repository = feature_flags_repository @@ -68,12 +69,11 @@ def perform def update_feature_flag(notification) return true if @feature_flags_repository.get_change_number.to_i >= notification.data['changeNumber'] return false unless !notification.data['d'].nil? && @feature_flags_repository.get_change_number == notification.data['pcn'] - new_split = return_object_from_json(notification) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@feature_flags_repository, - [new_split], - notification.data['changeNumber'], @config, false) - fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, "IN_SEGMENT"), @feature_flags_repository) - if fetch_rule_based_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, "IN_RULE_BASED_SEGMENT"), notification.data['changeNumber']) + + update_feature_flag_repository(notification) + fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, 'IN_SEGMENT'), @feature_flags_repository) + if fetch_rule_based_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, 'IN_RULE_BASED_SEGMENT'), + notification.data['changeNumber']) return true end @@ -86,18 +86,26 @@ def update_feature_flag(notification) false end + def update_feature_flag_repository(notification) + new_split = return_object_from_json(notification) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@feature_flags_repository, [new_split], + notification.data['changeNumber'], @config, false) + end + def update_rule_based_segment(notification) return true if @rule_based_segment_repository.get_change_number.to_i >= notification.data['changeNumber'] - return false unless !notification.data['d'].nil? && @rule_based_segment_repository.get_change_number == notification.data['pcn'] + return false unless !notification.data['d'].nil? && + @rule_based_segment_repository.get_change_number == notification.data['pcn'] new_rb_segment = return_object_from_json(notification) SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segment_repository, - [new_rb_segment], - notification.data['changeNumber'], @config) - fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_rb_segment, "IN_SEGMENT"), @rule_based_segment_repository) + [new_rb_segment], + notification.data['changeNumber'], @config) + fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_rb_segment, 'IN_SEGMENT'), + @rule_based_segment_repository) -# TODO: enable when telemetry spec is added -# @telemetry_runtime_producer.record_updates_from_sse(Telemetry::Domain::Constants::SPLITS) + # TODO: enable when telemetry spec is added + # @telemetry_runtime_producer.record_updates_from_sse(Telemetry::Domain::Constants::SPLITS) true rescue StandardError => e @@ -110,11 +118,9 @@ def kill_feature_flag(notification) return if @feature_flags_repository.get_change_number.to_i > notification.data['changeNumber'] @config.logger.debug("feature_flags_worker kill #{notification.data['splitName']}, #{notification.data['changeNumber']}") - @feature_flags_repository.kill( - notification.data['changeNumber'], - notification.data['splitName'], - notification.data['defaultTreatment'] - ) + @feature_flags_repository.kill(notification.data['changeNumber'], + notification.data['splitName'], + notification.data['defaultTreatment']) @synchronizer.fetch_splits(notification.data['changeNumber'], 0) end @@ -124,7 +130,6 @@ def return_object_from_json(notification) end def fetch_segments_if_not_exists(segment_names, object_repository) - return if segment_names.nil? object_repository.set_segment_names(segment_names) @@ -132,9 +137,8 @@ def fetch_segments_if_not_exists(segment_names, object_repository) end def fetch_rule_based_segments_if_not_exists(segment_names, change_number) - if segment_names.nil? or segment_names.empty? or @rule_based_segment_repository.contains?(segment_names.to_a) - return false - end + return false if segment_names.nil? || segment_names.empty? || @rule_based_segment_repository.contains?(segment_names.to_a) + @synchronizer.fetch_splits(0, change_number) true From 1952d9d0da9e59e0f0bb9ddb13edb9e199709e26 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 16 May 2025 10:04:14 -0700 Subject: [PATCH 05/11] polish --- lib/splitclient-rb/helpers/repository_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/splitclient-rb/helpers/repository_helper.rb b/lib/splitclient-rb/helpers/repository_helper.rb index eb790447..da72ad22 100644 --- a/lib/splitclient-rb/helpers/repository_helper.rb +++ b/lib/splitclient-rb/helpers/repository_helper.rb @@ -13,7 +13,7 @@ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, next end - feature_flag = self.check_impressions_disabled(feature_flag, config) + feature_flag = check_impressions_disabled(feature_flag, config) config.logger.debug("storing feature flag (#{feature_flag[:name]})") if config.debug_enabled to_add.push(feature_flag) From a2ce544eaa88905290d622953ae5fba2285690b6 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 16 May 2025 10:05:02 -0700 Subject: [PATCH 06/11] fix sse issue --- .../engine/matchers/rule_based_segment_matcher.rb | 6 +++--- lib/splitclient-rb/helpers/repository_helper.rb | 2 +- lib/splitclient-rb/sse/notification_processor.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb index 081c657c..74c5e2f4 100644 --- a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +++ b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb @@ -28,7 +28,7 @@ def match?(args) key = update_key(args) return false if rule_based_segment[:excluded][:keys].include?(key) - return false unless check_excluded_segments(rule_based_segment) + return false unless check_excluded_segments(rule_based_segment, key, args) matches = false rule_based_segment[:conditions].each do |c| @@ -44,7 +44,7 @@ def match?(args) private - def check_excluded_segments(rule_based_segment) + def check_excluded_segments(rule_based_segment, key, args) rule_based_segment[:excluded][:segments].each do |segment| return false if segment[:type] == 'standard' && @segments_repository.in_segment?(segment[:name], key) @@ -52,7 +52,7 @@ def check_excluded_segments(rule_based_segment) @rule_based_segments_repository.get_rule_based_segment(segment[:name]), args ) end - True + true end def update_key(args) diff --git a/lib/splitclient-rb/helpers/repository_helper.rb b/lib/splitclient-rb/helpers/repository_helper.rb index eb790447..da72ad22 100644 --- a/lib/splitclient-rb/helpers/repository_helper.rb +++ b/lib/splitclient-rb/helpers/repository_helper.rb @@ -13,7 +13,7 @@ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, next end - feature_flag = self.check_impressions_disabled(feature_flag, config) + feature_flag = check_impressions_disabled(feature_flag, config) config.logger.debug("storing feature flag (#{feature_flag[:name]})") if config.debug_enabled to_add.push(feature_flag) diff --git a/lib/splitclient-rb/sse/notification_processor.rb b/lib/splitclient-rb/sse/notification_processor.rb index d723cbdc..af5563c3 100644 --- a/lib/splitclient-rb/sse/notification_processor.rb +++ b/lib/splitclient-rb/sse/notification_processor.rb @@ -27,7 +27,7 @@ def process(incoming_notification) private def process_split_update(notification) - @config.logger.debug("#{notification.type} notification received: #{notification}") if @config.debug_enabled + @config.logger.debug("#{notification.event_type} notification received: #{notification}") if @config.debug_enabled @splits_worker.add_to_queue(notification) end From 1566bfbad6af04f38cc3173dcee81537d9d6e75e Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 16 May 2025 10:32:53 -0700 Subject: [PATCH 07/11] polish --- .../sse/workers/splits_worker.rb | 3 +- spec/engine/api/splits_spec.rb | 4 +- .../rule_based_segment_matcher_spec.rb | 4 +- spec/repository_helper.rb | 37 +++++++++++++------ 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/lib/splitclient-rb/sse/workers/splits_worker.rb b/lib/splitclient-rb/sse/workers/splits_worker.rb index 27ea916e..f1e83775 100644 --- a/lib/splitclient-rb/sse/workers/splits_worker.rb +++ b/lib/splitclient-rb/sse/workers/splits_worker.rb @@ -70,7 +70,7 @@ def update_feature_flag(notification) return true if @feature_flags_repository.get_change_number.to_i >= notification.data['changeNumber'] return false unless !notification.data['d'].nil? && @feature_flags_repository.get_change_number == notification.data['pcn'] - update_feature_flag_repository(notification) + new_split = update_feature_flag_repository(notification) fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, 'IN_SEGMENT'), @feature_flags_repository) if fetch_rule_based_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_split, 'IN_RULE_BASED_SEGMENT'), notification.data['changeNumber']) @@ -90,6 +90,7 @@ def update_feature_flag_repository(notification) new_split = return_object_from_json(notification) SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(@feature_flags_repository, [new_split], notification.data['changeNumber'], @config, false) + new_split end def update_rule_based_segment(notification) diff --git a/spec/engine/api/splits_spec.rb b/spec/engine/api/splits_spec.rb index 2d293498..9c384a32 100644 --- a/spec/engine/api/splits_spec.rb +++ b/spec/engine/api/splits_spec.rb @@ -206,7 +206,7 @@ parsed_splits = splits_api.since(-1, -1) - expect(parsed_splits[:ff][:d].length()).to eq(7) + expect(parsed_splits[:ff][:d].length()).to eq(6) expect(parsed_splits[:ff][:t]).to eq(1457726098069) expect(parsed_splits[:ff][:s]).to eq(-1) expect(parsed_splits[:rbs]).to eq({:d => [], :s => -1, :t => -1}) @@ -220,7 +220,7 @@ .to_return(status: 200, body: old_spec_splits) parsed_splits = splits_api.since(-1, -1) - expect(parsed_splits[:ff][:d].length()).to eq(7) + expect(parsed_splits[:ff][:d].length()).to eq(6) expect(splits_api.instance_variable_get(:@spec_version)).to eq(SplitIoClient::Api::Splits::SPEC_1_1) SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 diff --git a/spec/engine/matchers/rule_based_segment_matcher_spec.rb b/spec/engine/matchers/rule_based_segment_matcher_spec.rb index f09b5422..ce2f9aba 100644 --- a/spec/engine/matchers/rule_based_segment_matcher_spec.rb +++ b/spec/engine/matchers/rule_based_segment_matcher_spec.rb @@ -32,7 +32,7 @@ expect(matcher.match?(value: 'key2')).to be false end - it 'return true if excluded rb segment is matched' do + it 'return false if excluded rb segment is matched' do rbs_repositoy = SplitIoClient::Cache::Repositories::RuleBasedSegmentsRepository.new(config) rbs = {:name => 'sample_rule_based_segment', :trafficTypeName => 'tt_name_1', :conditions => [], :excluded => {:keys => [], :segments => [{:name => 'no_excludes', :type => 'rule-based'}]}} rbs2 = {:name => 'no_excludes', :trafficTypeName => 'tt_name_1', @@ -60,7 +60,7 @@ rbs_repositoy.update([rbs, rbs2], [], -1) matcher = described_class.new(segments_repository, rbs_repositoy, 'sample_rule_based_segment', config) - expect(matcher.match?(value: 'bilal@split.io', attributes: {'email': 'bilal@split.io'})).to be true + expect(matcher.match?(value: 'bilal@split.io', attributes: {'email': 'bilal@split.io'})).to be false expect(matcher.match?(value: 'bilal', attributes: {'email': 'bilal'})).to be false end diff --git a/spec/repository_helper.rb b/spec/repository_helper.rb index 0f091f78..d38dff96 100644 --- a/spec/repository_helper.rb +++ b/spec/repository_helper.rb @@ -13,16 +13,16 @@ flag_sets_repository, flag_set_filter) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => ['set_1']}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', conditions: [], :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', conditions: [], :sets => ['set_1']}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) end @@ -35,16 +35,16 @@ flag_sets_repository, flag_set_filter) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config, false) expect(feature_flag_repository.get_split('split2').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split3', :status => 'ACTIVE', conditions: [], :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split3', :status => 'ACTIVE', conditions: [], :sets => ['set_1']}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', conditions: [], :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', conditions: [], :sets => ['set_1']}], -1, config, false) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) end @@ -57,16 +57,31 @@ flag_sets_repository, flag_set_filter) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config, false) expect(feature_flag_repository.get_split('split1')[:impressionsDisabled]).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :impressionsDisabled => false, :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :impressionsDisabled => false, :sets => []}], -1, config, false) expect(feature_flag_repository.get_split('split2')[:impressionsDisabled]).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :impressionsDisabled => true, :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :impressionsDisabled => true, :sets => []}], -1, config, false) expect(feature_flag_repository.get_split('split2')[:impressionsDisabled]).to eq(true) + end + + it 'test clear cache flag' do + config = SplitIoClient::SplitConfig.new(cache_adapter: :memory) + flag_set_filter = SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) + flag_sets_repository = SplitIoClient::Cache::Repositories::MemoryFlagSetsRepository.new([]) + feature_flag_repository = SplitIoClient::Cache::Repositories::SplitsRepository.new( + config, + flag_sets_repository, + flag_set_filter) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config, false) + expect(feature_flag_repository.get_split('split1').nil?).to eq(false) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config, true) + expect(feature_flag_repository.get_split('split2').nil?).to eq(false) + expect(feature_flag_repository.get_split('split1').nil?).to eq(true) end end end From ecd007b8f34868b5ddf975be9d1dd550fbb8617f Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 16 May 2025 12:15:51 -0700 Subject: [PATCH 08/11] updated split api --- lib/splitclient-rb/engine/api/splits.rb | 4 ++ spec/engine/api/splits_spec.rb | 29 +++++++- .../rule_based_segments/split_old_spec2.json | 66 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 spec/test_data/rule_based_segments/split_old_spec2.json diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index b8e08974..1b690e3b 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -16,6 +16,7 @@ def initialize(api_key, config, telemetry_runtime_producer) @spec_version = SplitIoClient::Spec::FeatureFlags::SPEC_VERSION @last_proxy_check_timestamp = 0 @clear_storage = false + @old_spec_since = nil end def since(since, since_rbs, fetch_options = { cache_control_headers: false, till: nil, sets: nil}) @@ -24,13 +25,16 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till if check_last_proxy_check_timestamp @spec_version = SplitIoClient::Spec::FeatureFlags::SPEC_VERSION @config.logger.debug("Switching to new Feature flag spec #{@spec_version} and fetching.") + @old_spec_since = since since = -1 since_rbs = -1 fetch_options = { cache_control_headers: false, till: nil, sets: nil} end if @spec_version == Splits::SPEC_1_1 + since = @old_spec_since unless @old_spec_since.nil? params = { s: @spec_version, since: since } + @old_spec_since = nil else params = { s: @spec_version, since: since, rbSince: since_rbs } end diff --git a/spec/engine/api/splits_spec.rb b/spec/engine/api/splits_spec.rb index 9c384a32..e5c4a47f 100644 --- a/spec/engine/api/splits_spec.rb +++ b/spec/engine/api/splits_spec.rb @@ -225,11 +225,38 @@ SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 sleep 1 - parsed_splits = splits_api.since(-1, -1) + parsed_splits = splits_api.since(1457726098069, -1) expect(splits_api.clear_storage).to eq(true) expect(parsed_splits[:ff][:d].length()).to eq(2) expect(parsed_splits[:rbs][:d].length()).to eq(1) expect(splits_api.instance_variable_get(:@spec_version)).to eq(SplitIoClient::Spec::FeatureFlags::SPEC_VERSION) + expect(splits_api.instance_variable_get(:@old_spec_since)).to eq(1457726098069) + end + + it 'check using old_spec_since variable' do + old_spec_splits2 = File.read(File.expand_path(File.join(File.dirname(__FILE__), '../../test_data/rule_based_segments/split_old_spec2.json'))) + + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.3&since=-1&rbSince=-1') + .to_return({status: 400, body: ''}, {status: 400, body: ''}) + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: old_spec_splits) + stub_request(:get, 'https://proxy-server/api/splitChanges?s=1.1&since=1457726098069') + .to_return(status: 200, body: old_spec_splits2) + + parsed_splits = splits_api.since(-1, -1) + expect(parsed_splits[:ff][:d].length()).to eq(6) + expect(splits_api.instance_variable_get(:@spec_version)).to eq(SplitIoClient::Api::Splits::SPEC_1_1) + + SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 1 + sleep 1 + parsed_splits = splits_api.since(1457726098069, -1) + SplitIoClient::Api::Splits::PROXY_CHECK_INTERVAL_SECONDS = 100000 + + sleep 1 + expect(splits_api.instance_variable_get(:@spec_version)).to eq(SplitIoClient::Api::Splits::SPEC_1_1) + expect(splits_api.instance_variable_get(:@old_spec_since)).to eq(nil) + expect(parsed_splits[:ff][:d].length()).to eq(1) + expect(log.string).to include 'Switching to new Feature flag spec 1.3 and fetching.' end end end diff --git a/spec/test_data/rule_based_segments/split_old_spec2.json b/spec/test_data/rule_based_segments/split_old_spec2.json new file mode 100644 index 00000000..74aff1ed --- /dev/null +++ b/spec/test_data/rule_based_segments/split_old_spec2.json @@ -0,0 +1,66 @@ +{ + "splits": [ + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "new_feature", + "seed": -1222652054, + "status": "ACTIVE", + "killed": false, + "changeNumber": 123, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "WHITELIST", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": { + "whitelist": [ + "whitelisted_user" + ] + } + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + } + ] + }, + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ] + } + ], + "sets": ["set1", "set2"] + } ], + "since": -1, + "till": 1457726098069 +} \ No newline at end of file From 3a33ffcfabcf9f2d92b579e3f8cd5115a3a03e35 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 19 May 2025 15:45:46 -0700 Subject: [PATCH 09/11] updated util and test --- lib/splitclient-rb/engine/api/splits.rb | 10 +-------- lib/splitclient-rb/helpers/util.rb | 11 ++++++++++ .../sse/workers/splits_worker.rb | 2 +- spec/sse/workers/splits_worker_spec.rb | 21 ++++++++++++------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index b8e08974..a86397e1 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -115,15 +115,7 @@ def objects_with_segment_names(parsed_objects) end.flatten parsed_objects[:rbs][:d].each do |rule_based_segment| - parsed_objects[:segment_names].merge Helpers::Util.segment_names_by_object(rule_based_segment, "IN_SEGMENT") - end - - parsed_objects[:rbs][:d].each do |rule_based_segment| - rule_based_segment[:excluded][:segments].each do |segment| - if segment[:type] == "standard" - parsed_objects[:segment_names].add(segment[:name]) - end - end + parsed_objects[:segment_names].merge Helpers::Util.segment_names_in_rb_segment(rule_based_segment, "IN_SEGMENT") end parsed_objects diff --git a/lib/splitclient-rb/helpers/util.rb b/lib/splitclient-rb/helpers/util.rb index 0f61d0ca..3c6eff85 100644 --- a/lib/splitclient-rb/helpers/util.rb +++ b/lib/splitclient-rb/helpers/util.rb @@ -12,6 +12,17 @@ def self.segment_names_by_object(object, matcher_type) end end end + + def self.segment_names_in_rb_segment(object, matcher_type) + names = Set.new + names.merge segment_names_by_object(object, matcher_type) + object[:excluded][:segments].each do |segment| + if segment[:type] == 'standard' + names.add(segment[:name]) + end + end + names + end end end end diff --git a/lib/splitclient-rb/sse/workers/splits_worker.rb b/lib/splitclient-rb/sse/workers/splits_worker.rb index f1e83775..4fe7563e 100644 --- a/lib/splitclient-rb/sse/workers/splits_worker.rb +++ b/lib/splitclient-rb/sse/workers/splits_worker.rb @@ -102,7 +102,7 @@ def update_rule_based_segment(notification) SplitIoClient::Helpers::RepositoryHelper.update_rule_based_segment_repository(@rule_based_segment_repository, [new_rb_segment], notification.data['changeNumber'], @config) - fetch_segments_if_not_exists(Helpers::Util.segment_names_by_object(new_rb_segment, 'IN_SEGMENT'), + fetch_segments_if_not_exists(Helpers::Util.segment_names_in_rb_segment(new_rb_segment, 'IN_SEGMENT'), @rule_based_segment_repository) # TODO: enable when telemetry spec is added diff --git a/spec/sse/workers/splits_worker_spec.rb b/spec/sse/workers/splits_worker_spec.rb index 0ef724f9..1bc41bf8 100644 --- a/spec/sse/workers/splits_worker_spec.rb +++ b/spec/sse/workers/splits_worker_spec.rb @@ -22,7 +22,7 @@ let(:event_split_update_no_definition) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c": 0, "d":null}'), 'test') } let(:event_split_update_segments) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c":2,"d":"eJzcVFtr20wQ/SvhPK9AsnzTvpnPJp+po0DlppRgzFga2dusJLNapaRG/73Id7sOoU+FvmluZ3TOGXYDayhNVTx9W3NIGUOiKtlAQCWQSNq+FyeJ6yzcBTuex+T0qe86XrfrUkJBzH4AgXw3mVFlivl3eiWIA/BA6yImq4oc0nPdG/mIOYF0gpYfeO3AEyh3Ca/XDfxer+u2BUpLtiohMfhvOn4aQeBFad20paRLFkg4pUrbqWGyGecWEvbwPQ9cCMQrypccVtmCDaTX7feCnu+7nY7nCZBeFpAtgbjIU7WszPbPSshNvc0lah8/b05hoxkkvv4/no4m42gKgYxsvGJzb4pqDdn0ZguVNwsxCIenhh3SPriBk/OSLB/Z/Vgpy1qV9mE3MSRLDfwxD/kMSjKVb1dUpmgwVFxgVtezWmBNxp5RsDdlavkdCJTqJ2+tqmcCmhasIU+LOEEtftfg8+Nk8vjlzxV44beINce2ME3z2TEeDrEWVzKNw3k0un8YhTd0aiaGnKqck4iXDakrwcpdNjzdq9PChxIV+VEXt2F/UUvTC9Guyk/t90dfO+/Xro73w65z7y6cU/ndnvTdge7f9W8wmcw/jb5F1+79yybsX6c7U2lGPat/BQAA//9ygdKB"}'), 'test') } let(:event_split_update_rb_segments) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c":0,"d":"eyJjaGFuZ2VOdW1iZXIiOiAxMCwgInRyYWZmaWNUeXBlTmFtZSI6ICJ1c2VyIiwgIm5hbWUiOiAicmJzX2ZsYWciLCAidHJhZmZpY0FsbG9jYXRpb24iOiAxMDAsICJ0cmFmZmljQWxsb2NhdGlvblNlZWQiOiAxODI4Mzc3MzgwLCAic2VlZCI6IC0yODY2MTc5MjEsICJzdGF0dXMiOiAiQUNUSVZFIiwgImtpbGxlZCI6IGZhbHNlLCAiZGVmYXVsdFRyZWF0bWVudCI6ICJvZmYiLCAiYWxnbyI6IDIsICJjb25kaXRpb25zIjogW3siY29uZGl0aW9uVHlwZSI6ICJST0xMT1VUIiwgIm1hdGNoZXJHcm91cCI6IHsiY29tYmluZXIiOiAiQU5EIiwgIm1hdGNoZXJzIjogW3sia2V5U2VsZWN0b3IiOiB7InRyYWZmaWNUeXBlIjogInVzZXIifSwgIm1hdGNoZXJUeXBlIjogIklOX1JVTEVfQkFTRURfU0VHTUVOVCIsICJuZWdhdGUiOiBmYWxzZSwgInVzZXJEZWZpbmVkU2VnbWVudE1hdGNoZXJEYXRhIjogeyJzZWdtZW50TmFtZSI6ICJzYW1wbGVfcnVsZV9iYXNlZF9zZWdtZW50In19XX0sICJwYXJ0aXRpb25zIjogW3sidHJlYXRtZW50IjogIm9uIiwgInNpemUiOiAxMDB9LCB7InRyZWF0bWVudCI6ICJvZmYiLCAic2l6ZSI6IDB9XSwgImxhYmVsIjogImluIHJ1bGUgYmFzZWQgc2VnbWVudCBzYW1wbGVfcnVsZV9iYXNlZF9zZWdtZW50In0sIHsiY29uZGl0aW9uVHlwZSI6ICJST0xMT1VUIiwgIm1hdGNoZXJHcm91cCI6IHsiY29tYmluZXIiOiAiQU5EIiwgIm1hdGNoZXJzIjogW3sia2V5U2VsZWN0b3IiOiB7InRyYWZmaWNUeXBlIjogInVzZXIifSwgIm1hdGNoZXJUeXBlIjogIkFMTF9LRVlTIiwgIm5lZ2F0ZSI6IGZhbHNlfV19LCAicGFydGl0aW9ucyI6IFt7InRyZWF0bWVudCI6ICJvbiIsICJzaXplIjogMH0sIHsidHJlYXRtZW50IjogIm9mZiIsICJzaXplIjogMTAwfV0sICJsYWJlbCI6ICJkZWZhdWx0IHJ1bGUifV0sICJjb25maWd1cmF0aW9ucyI6IHt9LCAic2V0cyI6IFtdLCAiaW1wcmVzc2lvbnNEaXNhYmxlZCI6IGZhbHNlfQ=="}'), 'test') } - let(:event_rb_segment_update) { SplitIoClient::SSE::EventSource::StreamData.new("data", 12345, JSON.parse('{"type":"RB_SEGMENT_UPDATE","changeNumber":5564531221,"pcn":1234,"c":0,"d":"eyJjaGFuZ2VOdW1iZXIiOiA1LCAibmFtZSI6ICJzYW1wbGVfcnVsZV9iYXNlZF9zZWdtZW50IiwgInN0YXR1cyI6ICJBQ1RJVkUiLCAidHJhZmZpY1R5cGVOYW1lIjogInVzZXIiLCAiZXhjbHVkZWQiOiB7ImtleXMiOiBbIm1hdXJvQHNwbGl0LmlvIl0sICJzZWdtZW50cyI6IFtdfSwgImNvbmRpdGlvbnMiOiBbeyJtYXRjaGVyR3JvdXAiOiB7ImNvbWJpbmVyIjogIkFORCIsICJtYXRjaGVycyI6IFt7ImtleVNlbGVjdG9yIjogeyJ0cmFmZmljVHlwZSI6ICJ1c2VyIiwgImF0dHJpYnV0ZSI6ICJlbWFpbCJ9LCAibWF0Y2hlclR5cGUiOiAiRU5EU19XSVRIIiwgIm5lZ2F0ZSI6IGZhbHNlLCAid2hpdGVsaXN0TWF0Y2hlckRhdGEiOiB7IndoaXRlbGlzdCI6IFsiQHNwbGl0LmlvIl19fV19fV19"}'), 'test') } + let(:event_rb_segment_update) { SplitIoClient::SSE::EventSource::StreamData.new("data", 12345, JSON.parse('{"type":"RB_SEGMENT_UPDATE","changeNumber":5564531221,"pcn":1234,"c":0,"d":"eyJjaGFuZ2VOdW1iZXIiOiA1LCAibmFtZSI6ICJzYW1wbGVfcnVsZV9iYXNlZF9zZWdtZW50IiwgInN0YXR1cyI6ICJBQ1RJVkUiLCAidHJhZmZpY1R5cGVOYW1lIjogInVzZXIiLCAiZXhjbHVkZWQiOiB7ImtleXMiOiBbIm1hdXJvQHNwbGl0LmlvIl0sICJzZWdtZW50cyI6IFt7InR5cGUiOiAic3RhbmRhcmQiLCAibmFtZSI6ICJzZWdtZW50MSJ9XX0sICJjb25kaXRpb25zIjogW3sibWF0Y2hlckdyb3VwIjogeyJjb21iaW5lciI6ICJBTkQiLCAibWF0Y2hlcnMiOiBbeyJrZXlTZWxlY3RvciI6IHsidHJhZmZpY1R5cGUiOiAidXNlciIsICJhdHRyaWJ1dGUiOiAiZW1haWwifSwgIm1hdGNoZXJUeXBlIjogIklOX1NFR01FTlQiLCAibmVnYXRlIjogZmFsc2UsICJ1c2VyRGVmaW5lZFNlZ21lbnRNYXRjaGVyRGF0YSI6IHsic2VnbWVudE5hbWUiOiAiZGVtbyJ9fV19fV19"}'), 'test') } context 'add change number to queue' do let(:flag_sets_repository) {SplitIoClient::Cache::Repositories::MemoryFlagSetsRepository.new([])} @@ -309,7 +309,7 @@ "trafficTypeName": "user", "excluded":{ "keys":["mauro@split.io","gaston@split.io"], - "segments":[] + "segments":["segment1"] }, "conditions": [ { @@ -321,13 +321,11 @@ "trafficType": "user", "attribute": "email" }, - "matcherType": "ENDS_WITH", + "matcherType": "IN_SEGMENT", "negate": false, - "whitelistMatcherData": { - "whitelist": [ - "@split.io" - ] - } + "userDefinedSegmentMatcherData":{ + "segmentName":"demo" + }, } ] } @@ -358,6 +356,8 @@ end it 'process rb segment update' do + stub_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=-1').to_return(status: 200, body: '{"name":"maur-2","added":["admin"],"removed":[],"since":-1,"till":-1}}') + stub_request(:get, 'https://sdk.split.io/api/segmentChanges/demo?since=-1').to_return(status: 200, body: '{"name":"maur-2","added":["admin"],"removed":[],"since":-1,"till":-1}}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher, rule_based_segments_repository) worker.start @@ -366,6 +366,11 @@ sleep 2 rb_segment = rule_based_segments_repository.get_rule_based_segment("sample_rule_based_segment") expect(rb_segment[:name] == 'sample_rule_based_segment') + + expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/demo?since=-1')).to have_been_made.once + expect(segments_repository.used_segment_names[0]).to eq('demo') + expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=-1')).to have_been_made.once + expect(segments_repository.used_segment_names[1]).to eq('segment1') end end From 3fe83c5f4be2ab98dc53154c4c2cad937311cf02 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 20 May 2025 10:34:24 -0700 Subject: [PATCH 10/11] fix test --- spec/sse/workers/splits_worker_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/sse/workers/splits_worker_spec.rb b/spec/sse/workers/splits_worker_spec.rb index 1bc41bf8..74e00c51 100644 --- a/spec/sse/workers/splits_worker_spec.rb +++ b/spec/sse/workers/splits_worker_spec.rb @@ -309,7 +309,7 @@ "trafficTypeName": "user", "excluded":{ "keys":["mauro@split.io","gaston@split.io"], - "segments":["segment1"] + "segments":[{ "type": "standard", "name": "segment1"}] }, "conditions": [ { From d266ac9cfb7700820617dc4299c3cd976d3759d2 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 20 May 2025 10:55:30 -0700 Subject: [PATCH 11/11] polish --- lib/splitclient-rb.rb | 1 + .../engine/matchers/rule_based_segment_matcher.rb | 4 ++-- lib/splitclient-rb/engine/models/segment_type.rb | 4 ++++ lib/splitclient-rb/helpers/util.rb | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 lib/splitclient-rb/engine/models/segment_type.rb diff --git a/lib/splitclient-rb.rb b/lib/splitclient-rb.rb index b6d04f55..9de3bc5e 100644 --- a/lib/splitclient-rb.rb +++ b/lib/splitclient-rb.rb @@ -105,6 +105,7 @@ require 'splitclient-rb/engine/metrics/binary_search_latency_tracker' require 'splitclient-rb/engine/models/split' require 'splitclient-rb/engine/models/label' +require 'splitclient-rb/engine/models/segment_type' require 'splitclient-rb/engine/models/treatment' require 'splitclient-rb/engine/auth_api_client' require 'splitclient-rb/engine/back_off' diff --git a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb index 5143f606..a1cd9d61 100644 --- a/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +++ b/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb @@ -44,9 +44,9 @@ def match?(args) def check_excluded_segments(rule_based_segment, key, args) rule_based_segment[:excluded][:segments].each do |segment| - return false if segment[:type] == 'standard' && @segments_repository.in_segment?(segment[:name], key) + return false if segment[:type] == SplitIoClient::Engine::Models::SegmentType::STANDARD && @segments_repository.in_segment?(segment[:name], key) - return false if segment[:type] == 'rule-based' && match_rbs( + return false if segment[:type] == SplitIoClient::Engine::Models::SegmentType::RULE_BASED_SEGMENT && match_rbs( @rule_based_segments_repository.get_rule_based_segment(segment[:name]), args ) end diff --git a/lib/splitclient-rb/engine/models/segment_type.rb b/lib/splitclient-rb/engine/models/segment_type.rb new file mode 100644 index 00000000..48cfae9e --- /dev/null +++ b/lib/splitclient-rb/engine/models/segment_type.rb @@ -0,0 +1,4 @@ +class SplitIoClient::Engine::Models::SegmentType + STANDARD = 'standard' + RULE_BASED_SEGMENT = 'rule-based' +end diff --git a/lib/splitclient-rb/helpers/util.rb b/lib/splitclient-rb/helpers/util.rb index 3c6eff85..9a7de81c 100644 --- a/lib/splitclient-rb/helpers/util.rb +++ b/lib/splitclient-rb/helpers/util.rb @@ -17,7 +17,7 @@ def self.segment_names_in_rb_segment(object, matcher_type) names = Set.new names.merge segment_names_by_object(object, matcher_type) object[:excluded][:segments].each do |segment| - if segment[:type] == 'standard' + if segment[:type] == SplitIoClient::Engine::Models::SegmentType::STANDARD names.add(segment[:name]) end end