diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38dab547..1da52c42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: matrix: version: - '2.5.0' - - '3.1.1' + - '3.2.2' steps: - name: Checkout code @@ -56,7 +56,7 @@ jobs: run: echo "VERSION=$(cat lib/splitclient-rb/version.rb | grep VERSION | awk -F "'" '{print $2}')" >> $GITHUB_ENV - name: SonarQube Scan (Push) - if: matrix.version == '3.1.1' && github.event_name == 'push' + if: matrix.version == '3.2.2' && github.event_name == 'push' uses: SonarSource/sonarcloud-github-action@v1.9 env: SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} @@ -68,7 +68,7 @@ jobs: -Dsonar.projectVersion=${{ env.VERSION }} - name: SonarQube Scan (Pull Request) - if: matrix.version == '3.1.1' && github.event_name == 'pull_request' + if: matrix.version == '3.2.2' && github.event_name == 'pull_request' uses: SonarSource/sonarcloud-github-action@v1.9 env: SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} diff --git a/CHANGES.txt b/CHANGES.txt index 1f7497b9..6e1339d1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,8 @@ CHANGES +8.2.0 (Jul 18, 2023) +- Improved streaming architecture implementation to apply feature flag updates from the notification received which is now enhanced, improving efficiency and reliability of the whole update system. + 8.1.2 (May 15, 2023) - Updated terminology on the SDKs codebase to be more aligned with current standard without causing a breaking change. The core change is the term split for feature flag on things like logs and IntelliSense comments. diff --git a/lib/splitclient-rb.rb b/lib/splitclient-rb.rb index 57ea263e..bba7eb84 100644 --- a/lib/splitclient-rb.rb +++ b/lib/splitclient-rb.rb @@ -41,6 +41,8 @@ require 'splitclient-rb/clients/split_client' require 'splitclient-rb/managers/split_manager' require 'splitclient-rb/helpers/thread_helper' +require 'splitclient-rb/helpers/decryption_helper' +require 'splitclient-rb/helpers/util' require 'splitclient-rb/split_factory' require 'splitclient-rb/split_factory_builder' require 'splitclient-rb/split_config' diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index 8fea9141..10d4544c 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -46,21 +46,11 @@ def splits_with_segment_names(splits_json) parsed_splits[:segment_names] = parsed_splits[:splits].each_with_object(Set.new) do |split, splits| - splits << segment_names(split) + splits << Helpers::Util.segment_names_by_feature_flag(split) end.flatten parsed_splits end - - def segment_names(split) - split[:conditions].each_with_object(Set.new) do |condition, names| - condition[:matcherGroup][:matchers].each do |matcher| - next if matcher[:userDefinedSegmentMatcherData].nil? - - names << matcher[:userDefinedSegmentMatcherData][:segmentName] - end - end - end end end end diff --git a/lib/splitclient-rb/engine/push_manager.rb b/lib/splitclient-rb/engine/push_manager.rb index 9eba5e85..e36a9588 100644 --- a/lib/splitclient-rb/engine/push_manager.rb +++ b/lib/splitclient-rb/engine/push_manager.rb @@ -33,6 +33,7 @@ def start_sse def stop_sse @sse_handler.stop + SplitIoClient::Helpers::ThreadHelper.stop(:schedule_next_token_refresh, @config) rescue StandardError => e @config.logger.error(e.inspect) end diff --git a/lib/splitclient-rb/helpers/decryption_helper.rb b/lib/splitclient-rb/helpers/decryption_helper.rb new file mode 100644 index 00000000..5dc63128 --- /dev/null +++ b/lib/splitclient-rb/helpers/decryption_helper.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module SplitIoClient + NO_COMPRESSION = 0 + GZIP_COMPRESSION = 1 + ZLIB_COMPRESSION = 2 + + module Helpers + class DecryptionHelper + def self.get_encoded_definition(compression, data) + case compression + when NO_COMPRESSION + Base64.decode64(data) + when GZIP_COMPRESSION + gz = Zlib::GzipReader.new(StringIO.new(Base64.decode64(data))) + gz.read + when ZLIB_COMPRESSION + Zlib::Inflate.inflate(Base64.decode64(data)) + else + raise StandardError, 'Compression flag value is incorrect' + end + end + end + end +end diff --git a/lib/splitclient-rb/helpers/util.rb b/lib/splitclient-rb/helpers/util.rb new file mode 100644 index 00000000..0cf9aad2 --- /dev/null +++ b/lib/splitclient-rb/helpers/util.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module SplitIoClient + module Helpers + class Util + def self.segment_names_by_feature_flag(feature_flag) + feature_flag[:conditions].each_with_object(Set.new) do |condition, names| + condition[:matcherGroup][:matchers].each do |matcher| + next if matcher[:userDefinedSegmentMatcherData].nil? + + names << matcher[:userDefinedSegmentMatcherData][:segmentName] + end + end + end + end + end +end diff --git a/lib/splitclient-rb/split_config.rb b/lib/splitclient-rb/split_config.rb index 1f42a3f8..ba42db6f 100644 --- a/lib/splitclient-rb/split_config.rb +++ b/lib/splitclient-rb/split_config.rb @@ -320,7 +320,7 @@ def init_impressions_mode(impressions_mode, adapter) return :debug else default = adapter == :redis ? :debug : :optimized - @logger.error("You passed an invalid impressions_mode, impressions_mode should be one of the following values: :debug, :optimized or :none. Defaulting to #{default} mode") + @logger.error("You passed an invalid impressions_mode, impressions_mode should be one of the following values: :debug, :optimized or :none. Defaulting to #{default} mode") unless impressions_mode.nil? return default end end diff --git a/lib/splitclient-rb/split_factory.rb b/lib/splitclient-rb/split_factory.rb index 334d79db..4a18f4fa 100644 --- a/lib/splitclient-rb/split_factory.rb +++ b/lib/splitclient-rb/split_factory.rb @@ -184,7 +184,7 @@ def build_synchronizer def build_streaming_components @push_status_queue = Queue.new - splits_worker = SSE::Workers::SplitsWorker.new(@synchronizer, @config, @splits_repository) + splits_worker = SSE::Workers::SplitsWorker.new(@synchronizer, @config, @splits_repository, @runtime_producer, @segment_fetcher) segments_worker = SSE::Workers::SegmentsWorker.new(@synchronizer, @config, @segments_repository) notification_manager_keeper = SSE::NotificationManagerKeeper.new(@config, @runtime_producer, @push_status_queue) notification_processor = SSE::NotificationProcessor.new(@config, splits_worker, segments_worker) diff --git a/lib/splitclient-rb/sse/event_source/client.rb b/lib/splitclient-rb/sse/event_source/client.rb index 5c44c576..022894d6 100644 --- a/lib/splitclient-rb/sse/event_source/client.rb +++ b/lib/splitclient-rb/sse/event_source/client.rb @@ -92,7 +92,7 @@ def connect_stream(latch) raise 'eof exception' if partial_data == :eof rescue Errno::EBADF, IOError => e - @config.logger.error(e.inspect) + @config.logger.error(e.inspect) if @config.debug_enabled return nil rescue StandardError => e return nil if ENV['SPLITCLIENT_ENV'] == 'test' diff --git a/lib/splitclient-rb/sse/notification_processor.rb b/lib/splitclient-rb/sse/notification_processor.rb index 6bde38a3..0c137f59 100644 --- a/lib/splitclient-rb/sse/notification_processor.rb +++ b/lib/splitclient-rb/sse/notification_processor.rb @@ -26,16 +26,12 @@ def process(incoming_notification) def process_split_update(notification) @config.logger.debug("SPLIT UPDATE notification received: #{notification}") if @config.debug_enabled - @splits_worker.add_to_queue(notification.data['changeNumber']) + @splits_worker.add_to_queue(notification) end def process_split_kill(notification) @config.logger.debug("SPLIT KILL notification received: #{notification}") if @config.debug_enabled - change_number = notification.data['changeNumber'] - default_treatment = notification.data['defaultTreatment'] - split_name = notification.data['splitName'] - - @splits_worker.kill_split(change_number, split_name, default_treatment) + @splits_worker.add_to_queue(notification) end def process_segment_update(notification) diff --git a/lib/splitclient-rb/sse/workers/splits_worker.rb b/lib/splitclient-rb/sse/workers/splits_worker.rb index 48bccfa2..cb8b5d67 100644 --- a/lib/splitclient-rb/sse/workers/splits_worker.rb +++ b/lib/splitclient-rb/sse/workers/splits_worker.rb @@ -4,12 +4,14 @@ module SplitIoClient module SSE module Workers class SplitsWorker - def initialize(synchronizer, config, splits_repository) + def initialize(synchronizer, config, feature_flags_repository, telemetry_runtime_producer, segment_fetcher) @synchronizer = synchronizer @config = config - @splits_repository = splits_repository + @feature_flags_repository = feature_flags_repository @queue = Queue.new @running = Concurrent::AtomicBoolean.new(false) + @telemetry_runtime_producer = telemetry_runtime_producer + @segment_fetcher = segment_fetcher end def start @@ -29,36 +31,83 @@ def stop end @running.make_false - SplitIoClient::Helpers::ThreadHelper.stop(:split_update_worker, @config) + Helpers::ThreadHelper.stop(:split_update_worker, @config) end - def add_to_queue(change_number) - @config.logger.debug("feature_flags_worker add to queue #{change_number}") - @queue.push(change_number) + def add_to_queue(notification) + @config.logger.debug("feature_flags_worker add to queue #{notification.data['changeNumber']}") + @queue.push(notification) end - def kill_split(change_number, split_name, default_treatment) - return if @splits_repository.get_change_number.to_i > change_number + private - @config.logger.debug("feature_flags_worker kill #{split_name}, #{change_number}") - @splits_repository.kill(change_number, split_name, default_treatment) - add_to_queue(change_number) + def perform_thread + @config.threads[:split_update_worker] = Thread.new do + @config.logger.debug('starting feature_flags_worker ...') if @config.debug_enabled + perform + end end - private - def perform - while (change_number = @queue.pop) - @config.logger.debug("feature_flags_worker change_number dequeue #{change_number}") - @synchronizer.fetch_splits(change_number) + while (notification = @queue.pop) + @config.logger.debug("feature_flags_worker change_number dequeue #{notification.data['changeNumber']}") + case notification.data['type'] + when SSE::EventSource::EventTypes::SPLIT_UPDATE + success = update_feature_flag(notification) + @synchronizer.fetch_splits(notification.data['changeNumber']) unless success + when SSE::EventSource::EventTypes::SPLIT_KILL + kill_feature_flag(notification) + end end end - def perform_thread - @config.threads[:split_update_worker] = Thread.new do - @config.logger.debug('starting feature_flags_worker ...') if @config.debug_enabled - 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_split_from_json(notification) + if Engine::Models::Split.archived?(new_split) + @feature_flags_repository.remove_split(new_split) + else + @feature_flags_repository.add_split(new_split) + + fetch_segments_if_not_exists(new_split) end + + @feature_flags_repository.set_change_number(notification.data['changeNumber']) + @telemetry_runtime_producer.record_updates_from_sse(Telemetry::Domain::Constants::SPLITS) + + true + rescue StandardError => e + @config.logger.debug("Failed to update Split: #{e.inspect}") if @config.debug_enabled + + false + end + + 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'] + ) + @synchronizer.fetch_splits(notification.data['changeNumber']) + end + + def return_split_from_json(notification) + split_json = Helpers::DecryptionHelper.get_encoded_definition(notification.data['c'], notification.data['d']) + + JSON.parse(split_json, symbolize_names: true) + end + + def fetch_segments_if_not_exists(feature_flag) + segment_names = Helpers::Util.segment_names_by_feature_flag(feature_flag) + return if segment_names.nil? + + @feature_flags_repository.set_segment_names(segment_names) + @segment_fetcher.fetch_segments_if_not_exists(segment_names) end end end diff --git a/lib/splitclient-rb/telemetry/domain/constants.rb b/lib/splitclient-rb/telemetry/domain/constants.rb index ed3f743c..c3ad34eb 100644 --- a/lib/splitclient-rb/telemetry/domain/constants.rb +++ b/lib/splitclient-rb/telemetry/domain/constants.rb @@ -36,6 +36,8 @@ class Constants TREATMENT_WITH_CONFIG = 'treatmentWithConfig' TREATMENTS_WITH_CONFIG = 'treatmentsWithConfig' TRACK = 'track' + + SPLITS = 'splits' end end end diff --git a/lib/splitclient-rb/telemetry/domain/structs.rb b/lib/splitclient-rb/telemetry/domain/structs.rb index 8d60abc0..c2d8b9d9 100644 --- a/lib/splitclient-rb/telemetry/domain/structs.rb +++ b/lib/splitclient-rb/telemetry/domain/structs.rb @@ -22,11 +22,14 @@ module Telemetry # ls: lastSynchronization, ml: clientMethodLatencies, me: clientMethodExceptions, he: httpErros, hl: httpLatencies, # tr: tokenRefreshes, ar: authRejections, iq: impressionsQueued, ide: impressionsDeduped, idr: impressionsDropped, # spc: splitsCount, sec: segmentCount, skc: segmentKeyCount, sl: sessionLengthMs, eq: eventsQueued, ed: eventsDropped, - # se: streamingEvents, t: tags - Usage = Struct.new(:ls, :ml, :me, :he, :hl, :tr, :ar, :iq, :ide, :idr, :spc, :sec, :skc, :sl, :eq, :ed, :se, :t) + # se: streamingEvents, t: tags, ufs: updates from sse + Usage = Struct.new(:ls, :ml, :me, :he, :hl, :tr, :ar, :iq, :ide, :idr, :spc, :sec, :skc, :sl, :eq, :ed, :se, :t, :ufs) # t: treatment, ts: treatments, tc: treatmentWithConfig, tcs: treatmentsWithConfig, tr: track ClientMethodLatencies = Struct.new(:t, :ts, :tc, :tcs, :tr) ClientMethodExceptions = Struct.new(:t, :ts, :tc, :tcs, :tr) + + # sp: splits + UpdatesFromSSE = Struct.new(:sp) end end diff --git a/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb b/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb index 37daf160..6787d904 100644 --- a/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb +++ b/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb @@ -94,6 +94,13 @@ def session_length @adapter.session_length.value end + def pop_updates_from_sse + splits = @adapter.updates_from_sse[Domain::Constants::SPLITS] + @adapter.updates_from_sse[Domain::Constants::SPLITS] = 0 + + UpdatesFromSSE.new(splits) + end + private def find_last_synchronization(type) diff --git a/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb b/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb index 80884ad5..602fa1b6 100644 --- a/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb +++ b/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb @@ -76,6 +76,12 @@ def record_session_length(session) rescue StandardError => e @config.log_found_exception(__method__.to_s, e) end + + def record_updates_from_sse(event) + @adapter.updates_from_sse[event] += 1 + rescue StandardError => e + @config.log_found_exception(__method__.to_s, e) + end end end end diff --git a/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb b/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb index 6d4ac313..45df5c59 100644 --- a/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +++ b/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb @@ -34,7 +34,8 @@ def synchronize_stats @telemetry_runtime_consumer.events_stats(Domain::Constants::EVENTS_QUEUED), @telemetry_runtime_consumer.events_stats(Domain::Constants::EVENTS_DROPPED), @telemetry_runtime_consumer.pop_streaming_events, - @telemetry_runtime_consumer.pop_tags) + @telemetry_runtime_consumer.pop_tags, + @telemetry_runtime_consumer.pop_updates_from_sse) @telemetry_api.record_stats(format_stats(usage)) rescue StandardError => e @@ -163,7 +164,8 @@ def format_stats(usage) eQ: usage.eq, eD: usage.ed, sE: usage.se, - t: usage.t + t: usage.t, + ufs: usage.ufs.to_h } end diff --git a/lib/splitclient-rb/telemetry/runtime_consumer.rb b/lib/splitclient-rb/telemetry/runtime_consumer.rb index f4c29792..7d044b74 100644 --- a/lib/splitclient-rb/telemetry/runtime_consumer.rb +++ b/lib/splitclient-rb/telemetry/runtime_consumer.rb @@ -14,7 +14,8 @@ class RuntimeConsumer :pop_auth_rejections, :pop_token_refreshes, :pop_streaming_events, - :session_length + :session_length, + :pop_updates_from_sse def initialize(config) @runtime = SplitIoClient::Telemetry::MemoryRuntimeConsumer.new(config) diff --git a/lib/splitclient-rb/telemetry/runtime_producer.rb b/lib/splitclient-rb/telemetry/runtime_producer.rb index a18f5f32..79dffac9 100644 --- a/lib/splitclient-rb/telemetry/runtime_producer.rb +++ b/lib/splitclient-rb/telemetry/runtime_producer.rb @@ -14,7 +14,8 @@ class RuntimeProducer :record_auth_rejections, :record_token_refreshes, :record_streaming_event, - :record_session_length + :record_session_length, + :record_updates_from_sse def initialize(config) @runtime = SplitIoClient::Telemetry::MemoryRuntimeProducer.new(config) diff --git a/lib/splitclient-rb/telemetry/storages/memory.rb b/lib/splitclient-rb/telemetry/storages/memory.rb index 8b111db3..bbe243db 100644 --- a/lib/splitclient-rb/telemetry/storages/memory.rb +++ b/lib/splitclient-rb/telemetry/storages/memory.rb @@ -16,7 +16,8 @@ class Memory :auth_rejections, :token_refreshes, :streaming_events, - :session_length + :session_length, + :updates_from_sse def initialize init_latencies @@ -32,6 +33,7 @@ def initialize init_streaming_events init_session_length init_tags + init_updates_from_sse end def init_latencies @@ -133,6 +135,12 @@ def init_streaming_events def init_session_length @session_length = Concurrent::AtomicFixnum.new(0) end + + def init_updates_from_sse + @updates_from_sse = Concurrent::Hash.new + + @updates_from_sse[Domain::Constants::SPLITS] = 0 + end end end end diff --git a/lib/splitclient-rb/version.rb b/lib/splitclient-rb/version.rb index 01b81d03..116ff706 100644 --- a/lib/splitclient-rb/version.rb +++ b/lib/splitclient-rb/version.rb @@ -1,3 +1,3 @@ module SplitIoClient - VERSION = '8.1.2' + VERSION = '8.2.0' end diff --git a/spec/engine/push_manager_spec.rb b/spec/engine/push_manager_spec.rb index 4904408c..215535bf 100644 --- a/spec/engine/push_manager_spec.rb +++ b/spec/engine/push_manager_spec.rb @@ -15,7 +15,7 @@ let(:runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } let(:split_fetcher) { SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_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) } + let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(split_fetcher, config, splits_repository, runtime_producer, segment_fetcher) } 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) } diff --git a/spec/engine/sync_manager_spec.rb b/spec/engine/sync_manager_spec.rb index b6891862..a8a5ee7a 100644 --- a/spec/engine/sync_manager_spec.rb +++ b/spec/engine/sync_manager_spec.rb @@ -48,7 +48,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) } let(:status_manager) { SplitIoClient::Engine::StatusManager.new(config) } - let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository) } + let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository, telemetry_runtime_producer, sync_params[:segment_fetcher]) } 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) } diff --git a/spec/integrations/push_client_spec.rb b/spec/integrations/push_client_spec.rb index f24ddf47..7bd17fb3 100644 --- a/spec/integrations/push_client_spec.rb +++ b/spec/integrations/push_client_spec.rb @@ -4,6 +4,11 @@ require 'http_server_mock' describe SplitIoClient do + let(:event_split_iff_update_no_compression) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850111, \\\"pcn\\\":1585948850110,\\\"c\\\": 0,\\\"d\\\":\\\"eyJ0cmFmZmljVHlwZU5hbWUiOiJ1c2VyIiwiaWQiOiIzM2VhZmE1MC0xYTY1LTExZWQtOTBkZi1mYTMwZDk2OTA0NDUiLCJuYW1lIjoiYmlsYWxfc3BsaXQiLCJ0cmFmZmljQWxsb2NhdGlvbiI6MTAwLCJ0cmFmZmljQWxsb2NhdGlvblNlZWQiOi0xMzY0MTE5MjgyLCJzZWVkIjotNjA1OTM4ODQzLCJzdGF0dXMiOiJBQ1RJVkUiLCJraWxsZWQiOmZhbHNlLCJkZWZhdWx0VHJlYXRtZW50Ijoib2ZmIiwiY2hhbmdlTnVtYmVyIjoxNjg0MzQwOTA4NDc1LCJhbGdvIjoyLCJjb25maWd1cmF0aW9ucyI6e30sImNvbmRpdGlvbnMiOlt7ImNvbmRpdGlvblR5cGUiOiJST0xMT1VUIiwibWF0Y2hlckdyb3VwIjp7ImNvbWJpbmVyIjoiQU5EIiwibWF0Y2hlcnMiOlt7ImtleVNlbGVjdG9yIjp7InRyYWZmaWNUeXBlIjoidXNlciJ9LCJtYXRjaGVyVHlwZSI6IklOX1NFR01FTlQiLCJuZWdhdGUiOmZhbHNlLCJ1c2VyRGVmaW5lZFNlZ21lbnRNYXRjaGVyRGF0YSI6eyJzZWdtZW50TmFtZSI6ImJpbGFsX3NlZ21lbnQifX1dfSwicGFydGl0aW9ucyI6W3sidHJlYXRtZW50Ijoib24iLCJzaXplIjowfSx7InRyZWF0bWVudCI6Im9mZiIsInNpemUiOjEwMH1dLCJsYWJlbCI6ImluIHNlZ21lbnQgYmlsYWxfc2VnbWVudCJ9LHsiY29uZGl0aW9uVHlwZSI6IlJPTExPVVQiLCJtYXRjaGVyR3JvdXAiOnsiY29tYmluZXIiOiJBTkQiLCJtYXRjaGVycyI6W3sia2V5U2VsZWN0b3IiOnsidHJhZmZpY1R5cGUiOiJ1c2VyIn0sIm1hdGNoZXJUeXBlIjoiQUxMX0tFWVMiLCJuZWdhdGUiOmZhbHNlfV19LCJwYXJ0aXRpb25zIjpbeyJ0cmVhdG1lbnQiOiJvbiIsInNpemUiOjB9LHsidHJlYXRtZW50Ijoib2ZmIiwic2l6ZSI6MTAwfV0sImxhYmVsIjoiZGVmYXVsdCBydWxlIn1dfQ==\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } + let(:event_split_iff_update_incorrect_pcn) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850111, \\\"pcn\\\":1234,\\\"c\\\": 0,\\\"d\\\":\\\"eyJ0cmFmZmljVHlwZU5hbWUiOiJ1c2VyIiwiaWQiOiIzM2VhZmE1MC0xYTY1LTExZWQtOTBkZi1mYTMwZDk2OTA0NDUiLCJuYW1lIjoiYmlsYWxfc3BsaXQiLCJ0cmFmZmljQWxsb2NhdGlvbiI6MTAwLCJ0cmFmZmljQWxsb2NhdGlvblNlZWQiOi0xMzY0MTE5MjgyLCJzZWVkIjotNjA1OTM4ODQzLCJzdGF0dXMiOiJBQ1RJVkUiLCJraWxsZWQiOmZhbHNlLCJkZWZhdWx0VHJlYXRtZW50Ijoib2ZmIiwiY2hhbmdlTnVtYmVyIjoxNjg0MzQwOTA4NDc1LCJhbGdvIjoyLCJjb25maWd1cmF0aW9ucyI6e30sImNvbmRpdGlvbnMiOlt7ImNvbmRpdGlvblR5cGUiOiJST0xMT1VUIiwibWF0Y2hlckdyb3VwIjp7ImNvbWJpbmVyIjoiQU5EIiwibWF0Y2hlcnMiOlt7ImtleVNlbGVjdG9yIjp7InRyYWZmaWNUeXBlIjoidXNlciJ9LCJtYXRjaGVyVHlwZSI6IklOX1NFR01FTlQiLCJuZWdhdGUiOmZhbHNlLCJ1c2VyRGVmaW5lZFNlZ21lbnRNYXRjaGVyRGF0YSI6eyJzZWdtZW50TmFtZSI6ImJpbGFsX3NlZ21lbnQifX1dfSwicGFydGl0aW9ucyI6W3sidHJlYXRtZW50Ijoib24iLCJzaXplIjowfSx7InRyZWF0bWVudCI6Im9mZiIsInNpemUiOjEwMH1dLCJsYWJlbCI6ImluIHNlZ21lbnQgYmlsYWxfc2VnbWVudCJ9LHsiY29uZGl0aW9uVHlwZSI6IlJPTExPVVQiLCJtYXRjaGVyR3JvdXAiOnsiY29tYmluZXIiOiJBTkQiLCJtYXRjaGVycyI6W3sia2V5U2VsZWN0b3IiOnsidHJhZmZpY1R5cGUiOiJ1c2VyIn0sIm1hdGNoZXJUeXBlIjoiQUxMX0tFWVMiLCJuZWdhdGUiOmZhbHNlfV19LCJwYXJ0aXRpb25zIjpbeyJ0cmVhdG1lbnQiOiJvbiIsInNpemUiOjB9LHsidHJlYXRtZW50Ijoib2ZmIiwic2l6ZSI6MTAwfV0sImxhYmVsIjoiZGVmYXVsdCBydWxlIn1dfQ==\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } + let(:event_split_iff_update_missing_definition) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850111, \\\"pcn\\\":1585948850110,\\\"c\\\": 0,\\\"d\\\":\\\"\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } + let(:event_split_iff_update_incorrect_compression) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850111, \\\"pcn\\\":1585948850110,\\\"c\\\": 4,\\\"d\\\":\\\"eyJ0cmFmZmljVHlwZU5hbWUiOiJ1c2VyIiwiaWQiOiIzM2VhZmE1MC0xYTY1LTExZWQtOTBkZi1mYTMwZDk2OTA0NDUiLCJuYW1lIjoiYmlsYWxfc3BsaXQiLCJ0cmFmZmljQWxsb2NhdGlvbiI6MTAwLCJ0cmFmZmljQWxsb2NhdGlvblNlZWQiOi0xMzY0MTE5MjgyLCJzZWVkIjotNjA1OTM4ODQzLCJzdGF0dXMiOiJBQ1RJVkUiLCJraWxsZWQiOmZhbHNlLCJkZWZhdWx0VHJlYXRtZW50Ijoib2ZmIiwiY2hhbmdlTnVtYmVyIjoxNjg0MzQwOTA4NDc1LCJhbGdvIjoyLCJjb25maWd1cmF0aW9ucyI6e30sImNvbmRpdGlvbnMiOlt7ImNvbmRpdGlvblR5cGUiOiJST0xMT1VUIiwibWF0Y2hlckdyb3VwIjp7ImNvbWJpbmVyIjoiQU5EIiwibWF0Y2hlcnMiOlt7ImtleVNlbGVjdG9yIjp7InRyYWZmaWNUeXBlIjoidXNlciJ9LCJtYXRjaGVyVHlwZSI6IklOX1NFR01FTlQiLCJuZWdhdGUiOmZhbHNlLCJ1c2VyRGVmaW5lZFNlZ21lbnRNYXRjaGVyRGF0YSI6eyJzZWdtZW50TmFtZSI6ImJpbGFsX3NlZ21lbnQifX1dfSwicGFydGl0aW9ucyI6W3sidHJlYXRtZW50Ijoib24iLCJzaXplIjowfSx7InRyZWF0bWVudCI6Im9mZiIsInNpemUiOjEwMH1dLCJsYWJlbCI6ImluIHNlZ21lbnQgYmlsYWxfc2VnbWVudCJ9LHsiY29uZGl0aW9uVHlwZSI6IlJPTExPVVQiLCJtYXRjaGVyR3JvdXAiOnsiY29tYmluZXIiOiJBTkQiLCJtYXRjaGVycyI6W3sia2V5U2VsZWN0b3IiOnsidHJhZmZpY1R5cGUiOiJ1c2VyIn0sIm1hdGNoZXJUeXBlIjoiQUxMX0tFWVMiLCJuZWdhdGUiOmZhbHNlfV19LCJwYXJ0aXRpb25zIjpbeyJ0cmVhdG1lbnQiOiJvbiIsInNpemUiOjB9LHsidHJlYXRtZW50Ijoib2ZmIiwic2l6ZSI6MTAwfV0sImxhYmVsIjoiZGVmYXVsdCBydWxlIn1dfQ==\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } + let(:event_split_update_missing_change_number) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } let(:event_split_update_must_fetch) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850111}\",\"name\":\"asdasd\"}\n\n\r\n" } let(:event_split_update_must_not_fetch) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850100}\",\"name\":\"asdasd\"}\n\n\r\n" } let(:event_split_kill_must_fetch) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_KILL\\\",\\\"changeNumber\\\": 1585948850111, \\\"defaultTreatment\\\" : \\\"off_kill\\\", \\\"splitName\\\" : \\\"push_test\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } @@ -107,6 +112,151 @@ client.destroy end end + + it 'processing split update missing change number' do + mock_splits_request(splits, -1) + mock_splits_request(splits2, 1_585_948_850_109) + mock_segment_changes('segment3', segment3, '-1') + stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') + + mock_server do |server| + server.setup_response('/') do |_, res| + send_content(res, event_split_update_missing_change_number) + end + + stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + + streaming_service_url = server.base_uri + factory = SplitIoClient::SplitFactory.new( + 'test_api_key', + streaming_enabled: true, + streaming_service_url: streaming_service_url, + auth_service_url: auth_service_url + ) + + client = factory.client + 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?since=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850109')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110')).to have_been_made.times(0) + end + end + + it 'processing split iff update event' do + mock_splits_request(splits, -1) + mock_splits_request(splits2, '1585948850109') + 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: '') + mock_server do |server| + server.setup_response('/') do |_, res| + send_content(res, event_split_iff_update_no_compression) + end + + stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + + streaming_service_url = server.base_uri + factory = SplitIoClient::SplitFactory.new( + 'test_api_key', + streaming_service_url: streaming_service_url, + auth_service_url: auth_service_url + ) + + client = factory.client + client.block_until_ready + sleep(2) + expect(client.get_treatment('admin', 'bilal_split')).to eq('off') + end + end + + it 'processing incorrect split iff update event' do + mock_splits_request(splits, -1) + mock_splits_request(splits2, '1585948850109') + 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?since=1585948850111').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).to_return(status: 200, body: auth_body_response) + + streaming_service_url = server.base_uri + factory = SplitIoClient::SplitFactory.new( + 'test_api_key', + streaming_service_url: streaming_service_url, + auth_service_url: auth_service_url + ) + + client = factory.client + client.block_until_ready + sleep(2) + expect(client.get_treatment('admin', 'bilal_split')).to eq('control') + expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') + end + end + + it 'processing split iff update event missing definition' do + mock_splits_request(splits, -1) + mock_splits_request(splits2, '1585948850109') + 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?since=1585948850111').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).to_return(status: 200, body: auth_body_response) + + streaming_service_url = server.base_uri + factory = SplitIoClient::SplitFactory.new( + 'test_api_key', + streaming_service_url: streaming_service_url, + auth_service_url: auth_service_url + ) + + client = factory.client + client.block_until_ready + sleep(2) + expect(client.get_treatment('admin', 'bilal_split')).to eq('control') + expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') + end + end + + it 'processing split iff update event incorrect compression' do + mock_splits_request(splits, -1) + mock_splits_request(splits2, '1585948850109') + 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?since=1585948850111').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).to_return(status: 200, body: auth_body_response) + + streaming_service_url = server.base_uri + factory = SplitIoClient::SplitFactory.new( + 'test_api_key', + streaming_service_url: streaming_service_url, + auth_service_url: auth_service_url + ) + + client = factory.client + client.block_until_ready + sleep(2) + expect(client.get_treatment('admin', 'bilal_split')).to eq('control') + expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') + end + end end context 'SPLIT_KILL' do diff --git a/spec/sse/event_source/client_spec.rb b/spec/sse/event_source/client_spec.rb index ae65f5a4..ffae8516 100644 --- a/spec/sse/event_source/client_spec.rb +++ b/spec/sse/event_source/client_spec.rb @@ -30,7 +30,7 @@ } end let(:synchronizer) { SplitIoClient::Engine::Synchronizer.new(repositories, config, parameters) } - let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, repositories[:splits]) } + let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, repositories[:splits], telemetry_runtime_producer, parameters[:segment_fetcher]) } let(:segments_worker) { SplitIoClient::SSE::Workers::SegmentsWorker.new(synchronizer, config, repositories[:segments]) } let(:push_status_queue) { Queue.new } let(:notification_manager_keeper) { SplitIoClient::SSE::NotificationManagerKeeper.new(config, telemetry_runtime_producer, push_status_queue) } diff --git a/spec/sse/sse_handler_spec.rb b/spec/sse/sse_handler_spec.rb index 231fb0be..28fcb1ed 100644 --- a/spec/sse/sse_handler_spec.rb +++ b/spec/sse/sse_handler_spec.rb @@ -31,7 +31,7 @@ } end let(:synchronizer) { SplitIoClient::Engine::Synchronizer.new(repositories, config, parameters) } - let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository) } + let(:splits_worker) { SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository, telemetry_runtime_producer, parameters[:segment_fetcher]) } 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) } diff --git a/spec/sse/workers/splits_worker_spec.rb b/spec/sse/workers/splits_worker_spec.rb index 0bfc7845..9ac38740 100644 --- a/spec/sse/workers/splits_worker_spec.rb +++ b/spec/sse/workers/splits_worker_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' require 'http_server_mock' +require 'byebug' describe SplitIoClient::SSE::Workers::SplitsWorker do subject { SplitIoClient::SSE::Workers::SplitsWorker } @@ -16,8 +17,15 @@ let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config) } let(:telemetry_runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } let(:split_fetcher) { SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_repository, api_key, config, telemetry_runtime_producer) } + let(:segment_fetcher) { SplitIoClient::Cache::Fetchers::SegmentFetcher.new(segments_repository, api_key, config, telemetry_runtime_producer) } + let(:event_split_update_no_compression) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c": 0,"d":"eyJ0cmFmZmljVHlwZU5hbWUiOiJ1c2VyIiwiaWQiOiIzM2VhZmE1MC0xYTY1LTExZWQtOTBkZi1mYTMwZDk2OTA0NDUiLCJuYW1lIjoiYmlsYWxfc3BsaXQiLCJ0cmFmZmljQWxsb2NhdGlvbiI6MTAwLCJ0cmFmZmljQWxsb2NhdGlvblNlZWQiOi0xMzY0MTE5MjgyLCJzZWVkIjotNjA1OTM4ODQzLCJzdGF0dXMiOiJBQ1RJVkUiLCJraWxsZWQiOmZhbHNlLCJkZWZhdWx0VHJlYXRtZW50Ijoib2ZmIiwiY2hhbmdlTnVtYmVyIjoxNjg0MzQwOTA4NDc1LCJhbGdvIjoyLCJjb25maWd1cmF0aW9ucyI6e30sImNvbmRpdGlvbnMiOlt7ImNvbmRpdGlvblR5cGUiOiJST0xMT1VUIiwibWF0Y2hlckdyb3VwIjp7ImNvbWJpbmVyIjoiQU5EIiwibWF0Y2hlcnMiOlt7ImtleVNlbGVjdG9yIjp7InRyYWZmaWNUeXBlIjoidXNlciJ9LCJtYXRjaGVyVHlwZSI6IklOX1NFR01FTlQiLCJuZWdhdGUiOmZhbHNlLCJ1c2VyRGVmaW5lZFNlZ21lbnRNYXRjaGVyRGF0YSI6eyJzZWdtZW50TmFtZSI6ImJpbGFsX3NlZ21lbnQifX1dfSwicGFydGl0aW9ucyI6W3sidHJlYXRtZW50Ijoib24iLCJzaXplIjowfSx7InRyZWF0bWVudCI6Im9mZiIsInNpemUiOjEwMH1dLCJsYWJlbCI6ImluIHNlZ21lbnQgYmlsYWxfc2VnbWVudCJ9LHsiY29uZGl0aW9uVHlwZSI6IlJPTExPVVQiLCJtYXRjaGVyR3JvdXAiOnsiY29tYmluZXIiOiJBTkQiLCJtYXRjaGVycyI6W3sia2V5U2VsZWN0b3IiOnsidHJhZmZpY1R5cGUiOiJ1c2VyIn0sIm1hdGNoZXJUeXBlIjoiQUxMX0tFWVMiLCJuZWdhdGUiOmZhbHNlfV19LCJwYXJ0aXRpb25zIjpbeyJ0cmVhdG1lbnQiOiJvbiIsInNpemUiOjB9LHsidHJlYXRtZW50Ijoib2ZmIiwic2l6ZSI6MTAwfV0sImxhYmVsIjoiZGVmYXVsdCBydWxlIn1dfQ=="}'), 'test') } + let(:event_split_update_gzip_compression) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c": 1,"d":"H4sIAAkVZWQC/8WST0+DQBDFv0qzZ0ig/BF6a2xjGismUk2MaZopzOKmy9Isy0EbvrtDwbY2Xo233Tdv5se85cCMBs5FtvrYYwIlsglratTMYiKns+chcAgc24UwsF0Xczt2cm5z8Jw8DmPH9wPyqr5zKyTITb2XwpA4TJ5KWWVgRKXYxHWcX/QUkVi264W+68bjaGyxupdCJ4i9KPI9UgyYpibI9Ha1eJnT/J2QsnNxkDVaLEcOjTQrjWBKVIasFefky95BFZg05Zb2mrhh5I9vgsiL44BAIIuKTeiQVYqLotHHLyLOoT1quRjub4fztQuLxj89LpePzytClGCyd9R3umr21ErOcitUh2PTZHY29HN2+JGixMxUujNfvMB3+u2pY1AXySad3z3Mk46msACDp8W7jhly4uUpFt3qD33vDAx0gLpXkx+P1GusbdcE24M2F4uaywwVEWvxSa1Oa13Vjvn2RXradm0xCVuUVBJqNCBGV0DrX4OcLpeb+/lreh3jH8Uw/JQj3UhkxPgCCurdEnADAAA="}'), 'test') } + let(:event_split_update_zlib_compression) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c": 2,"d":"eJzEUtFq20AQ/JUwz2c4WZZr3ZupTQh1FKjcQinGrKU95cjpZE6nh9To34ssJ3FNX0sfd3Zm53b2TgietDbF9vXIGdUMha5lDwFTQiGOmTQlchLRPJlEEZeTVJZ6oimWZTpP5WyWQMCNyoOxZPft0ZoA8TZ5aW1TUDCNg4qk/AueM5dQkyiez6IonS6mAu0IzWWSxovFLBZoA4WuhcLy8/bh+xoCL8bagaXJtixQsqbOhq1nCjW7AIVGawgUz+Qqzrr6wB4qmi9m00/JIk7TZCpAtmqgpgJF47SpOn9+UQt16s9YaS71z9NHOYQFha9Pm83Tty0EagrFM/t733RHqIFZH4wb7LDMVh+Ecc4Lv+ZsuQiNH8hXF3hLv39XXNCHbJ+v7x/X2eDmuKLA74sPihVr47jMuRpWfxy1Kwo0GLQjmv1xpBFD3+96gSP5cLVouM7QQaA1vxhK9uKmd853bEZS9jsBSwe2UDDu7mJxd2Mo/muQy81m/2X9I7+N8R/FcPmUd76zjH7X/w4AAP//90glTw=="}'), 'test') } + let(:event_split_archived_no_compression) { SplitIoClient::SSE::EventSource::StreamData.new("data", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":5564531221,"pcn":1234,"c": 0,"d":"eyJ0cmFmZmljVHlwZU5hbWUiOiAidXNlciIsICJpZCI6ICIzM2VhZmE1MC0xYTY1LTExZWQtOTBkZi1mYTMwZDk2OTA0NDUiLCAibmFtZSI6ICJiaWxhbF9zcGxpdCIsICJ0cmFmZmljQWxsb2NhdGlvbiI6IDEwMCwgInRyYWZmaWNBbGxvY2F0aW9uU2VlZCI6IC0xMzY0MTE5MjgyLCAic2VlZCI6IC02MDU5Mzg4NDMsICJzdGF0dXMiOiAiQVJDSElWRUQiLCAia2lsbGVkIjogZmFsc2UsICJkZWZhdWx0VHJlYXRtZW50IjogIm9mZiIsICJjaGFuZ2VOdW1iZXIiOiAxNjg0Mjc1ODM5OTUyLCAiYWxnbyI6IDIsICJjb25maWd1cmF0aW9ucyI6IHt9LCAiY29uZGl0aW9ucyI6IFt7ImNvbmRpdGlvblR5cGUiOiAiUk9MTE9VVCIsICJtYXRjaGVyR3JvdXAiOiB7ImNvbWJpbmVyIjogIkFORCIsICJtYXRjaGVycyI6IFt7ImtleVNlbGVjdG9yIjogeyJ0cmFmZmljVHlwZSI6ICJ1c2VyIn0sICJtYXRjaGVyVHlwZSI6ICJJTl9TRUdNRU5UIiwgIm5lZ2F0ZSI6IGZhbHNlLCAidXNlckRlZmluZWRTZWdtZW50TWF0Y2hlckRhdGEiOiB7InNlZ21lbnROYW1lIjogImJpbGFsX3NlZ21lbnQifX1dfSwgInBhcnRpdGlvbnMiOiBbeyJ0cmVhdG1lbnQiOiAib24iLCAic2l6ZSI6IDB9LCB7InRyZWF0bWVudCI6ICJvZmYiLCAic2l6ZSI6IDEwMH1dLCAibGFiZWwiOiAiaW4gc2VnbWVudCBiaWxhbF9zZWdtZW50In0sIHsiY29uZGl0aW9uVHlwZSI6ICJST0xMT1VUIiwgIm1hdGNoZXJHcm91cCI6IHsiY29tYmluZXIiOiAiQU5EIiwgIm1hdGNoZXJzIjogW3sia2V5U2VsZWN0b3IiOiB7InRyYWZmaWNUeXBlIjogInVzZXIifSwgIm1hdGNoZXJUeXBlIjogIkFMTF9LRVlTIiwgIm5lZ2F0ZSI6IGZhbHNlfV19LCAicGFydGl0aW9ucyI6IFt7InRyZWF0bWVudCI6ICJvbiIsICJzaXplIjogMH0sIHsidHJlYXRtZW50IjogIm9mZiIsICJzaXplIjogMTAwfV0sICJsYWJlbCI6ICJkZWZhdWx0IHJ1bGUifV19"}'), 'test') } + 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(:segments_repository) { SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) } let(:synchronizer) do - segments_repository = SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) telemetry_api = SplitIoClient::Api::TelemetryApi.new(config, api_key, telemetry_runtime_producer) impressions_api = SplitIoClient::Api::Impressions.new(api_key, config, telemetry_runtime_producer) @@ -27,8 +35,8 @@ } params = { - split_fetcher: SplitIoClient::Cache::Fetchers::SplitFetcher.new(splits_repository, api_key, config, telemetry_runtime_producer), - segment_fetcher: SplitIoClient::Cache::Fetchers::SegmentFetcher.new(segments_repository, api_key, config, telemetry_runtime_producer), + split_fetcher: split_fetcher, + segment_fetcher: segment_fetcher, imp_counter: SplitIoClient::Engine::Common::ImpressionCounter.new, impressions_sender_adapter: SplitIoClient::Cache::Senders::ImpressionsSenderAdapter.new(config, telemetry_api, impressions_api), impressions_api: SplitIoClient::Api::Impressions.new(api_key, config, telemetry_runtime_producer) @@ -43,9 +51,9 @@ stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918').to_return(status: 200, body: '{"splits": [],"since": 1506703262918,"till": 1506703262918}') stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918&till=1506703262919').to_return(status: 200, body: '{"splits": [],"since": 1506703262919,"till": 1506703262919}') - worker = subject.new(synchronizer, config, splits_repository) + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start - worker.add_to_queue(1_506_703_262_919) + worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262919}'), 'test')) sleep 1 @@ -58,9 +66,9 @@ stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262916}') stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '{"splits": [],"since": 1506703262916,"till": 1506703262918}') - worker = subject.new(synchronizer, config, splits_repository) + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start - worker.add_to_queue(1_506_703_262_918) + worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262918}'), 'test')) sleep 1 expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.once @@ -69,17 +77,17 @@ it 'must not trigger fetch' do stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262916}') - worker = subject.new(synchronizer, config, splits_repository) + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start - worker.add_to_queue(1_506_703_262_916) + worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262916}'), 'test')) sleep 1 expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.times(0) end it 'without start, must not fetch' do - worker = subject.new(synchronizer, config, splits_repository) - worker.add_to_queue(1_506_703_262_918) + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) + worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262918}'), 'test')) expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.times(0) end @@ -100,9 +108,9 @@ it 'must kill split and trigger fetch' do stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '{"splits": [],"since": 1506703262916,"till": 1506703262918}') - worker = subject.new(synchronizer, config, splits_repository) + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start - worker.kill_split(1_506_703_262_918, 'FACUNDO_TEST', 'on') + worker.send :kill_feature_flag, SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_KILL", 123, JSON.parse('{"splitName":"FACUNDO_TEST", "defaultTreatment":"on", "type":"SPLIT_KILL","changeNumber":1506703262918}'), 'test') sleep(1) @@ -114,10 +122,10 @@ end it 'must kill split and must not trigger fetch' do - worker = subject.new(synchronizer, config, splits_repository) + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start - worker.kill_split(1_506_703_262_916, 'FACUNDO_TEST', 'on') + worker.send :kill_feature_flag, SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_KILL", 123, JSON.parse('{"splitName":"FACUNDO_TEST", "defaultTreatment":"on", "type":"SPLIT_KILL","changeNumber":1506703262916}'), 'test') sleep(1) @@ -129,6 +137,61 @@ end end + context 'instant ff update split notification' do + it 'decode and decompress split update data' do + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) + worker.start + + splits_repository.set_change_number(1234) + worker.add_to_queue(event_split_update_no_compression) + sleep 1 + split = splits_repository.get_split('bilal_split') + expect(split[:name] == 'bilal_split') + + splits_repository.set_change_number(1234) + worker.add_to_queue(event_split_update_gzip_compression) + sleep 1 + split = splits_repository.get_split('bilal_split') + expect(split[:name] == 'bilal_split') + + splits_repository.set_change_number(1234) + worker.add_to_queue(event_split_update_zlib_compression) + sleep 1 + split = splits_repository.get_split('bilal_split') + expect(split[:name] == 'bilal_split') + + splits_repository.set_change_number(1234) + worker.add_to_queue(event_split_archived_no_compression) + sleep 1 + expect(splits_repository.exists?('bilal_split') == false) + end + + it 'instant ff update split notification with segment matcher.' do + stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1234').to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 1234}') + stub_request(:get, 'https://sdk.split.io/api/segmentChanges/maur-2?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) + worker.start + + splits_repository.set_change_number(1234) + worker.add_to_queue(event_split_update_segments) + sleep 1 + + expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/maur-2?since=-1')).to have_been_made.once + expect(segments_repository.used_segment_names[0]).to eq('maur-2') + end + + it 'should not update if definition is nil' do + stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1234').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262918}') + worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) + worker.start + + splits_repository.set_change_number(1234) + worker.add_to_queue(event_split_update_no_definition) + sleep 1 + expect(splits_repository.exists?('bilal_split') == false) + end + end + private def mock_split_changes(splits_json) diff --git a/spec/telemetry/synchronizer_spec.rb b/spec/telemetry/synchronizer_spec.rb index 48c5acfb..94b4e716 100644 --- a/spec/telemetry/synchronizer_spec.rb +++ b/spec/telemetry/synchronizer_spec.rb @@ -42,8 +42,8 @@ let(:init_producer) { SplitIoClient::Telemetry::InitProducer.new(config) } let(:telemetry_api) { SplitIoClient::Api::TelemetryApi.new(config, api_key, runtime_producer) } let(:telemetry_consumers) { { init: init_consumer, runtime: runtime_consumer, evaluation: evaluation_consumer } } - let(:body_usage) { "{\"lS\":{\"sp\":111111222,\"se\":111111222,\"im\":111111222,\"ic\":111111222,\"ev\":111111222,\"te\":111111222,\"to\":111111222},\"mL\":{\"t\":[0,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ts\":[0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tc\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tcs\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tr\":[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"mE\":{\"t\":2,\"ts\":1,\"tc\":1,\"tcs\":0,\"tr\":1},\"hE\":{\"sp\":{},\"se\":{\"400\":1},\"im\":{},\"ic\":{},\"ev\":{\"500\":2,\"501\":1},\"te\":{},\"to\":{}},\"hL\":{\"sp\":[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"se\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"im\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ic\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ev\":[0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"te\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"to\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"tR\":1,\"aR\":1,\"iQ\":3,\"iDe\":1,\"iDr\":2,\"spC\":3,\"seC\":3,\"skC\":7,\"sL\":444555,\"eQ\":4,\"eD\":1,\"sE\":[{\"e\":50,\"d\":222222333,\"t\":222222333},{\"e\":70,\"d\":0,\"t\":222222333},{\"e\":70,\"d\":1,\"t\":222222333}],\"t\":[\"tag-1\",\"tag-2\"]}" } - let(:empty_body_usage) { "{\"lS\":{\"sp\":0,\"se\":0,\"im\":0,\"ic\":0,\"ev\":0,\"te\":0,\"to\":0},\"mL\":{\"t\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ts\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tc\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tcs\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tr\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"mE\":{\"t\":0,\"ts\":0,\"tc\":0,\"tcs\":0,\"tr\":0},\"hE\":{\"sp\":{},\"se\":{},\"im\":{},\"ic\":{},\"ev\":{},\"te\":{},\"to\":{}},\"hL\":{\"sp\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"se\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"im\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ic\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ev\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"te\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"to\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"tR\":0,\"aR\":0,\"iQ\":0,\"iDe\":0,\"iDr\":0,\"spC\":0,\"seC\":0,\"skC\":0,\"sL\":0,\"eQ\":0,\"eD\":0,\"sE\":[],\"t\":[]}" } + let(:body_usage) { "{\"lS\":{\"sp\":111111222,\"se\":111111222,\"im\":111111222,\"ic\":111111222,\"ev\":111111222,\"te\":111111222,\"to\":111111222},\"mL\":{\"t\":[0,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ts\":[0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tc\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tcs\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tr\":[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"mE\":{\"t\":2,\"ts\":1,\"tc\":1,\"tcs\":0,\"tr\":1},\"hE\":{\"sp\":{},\"se\":{\"400\":1},\"im\":{},\"ic\":{},\"ev\":{\"500\":2,\"501\":1},\"te\":{},\"to\":{}},\"hL\":{\"sp\":[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"se\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"im\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ic\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ev\":[0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"te\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"to\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"tR\":1,\"aR\":1,\"iQ\":3,\"iDe\":1,\"iDr\":2,\"spC\":3,\"seC\":3,\"skC\":7,\"sL\":444555,\"eQ\":4,\"eD\":1,\"sE\":[{\"e\":50,\"d\":222222333,\"t\":222222333},{\"e\":70,\"d\":0,\"t\":222222333},{\"e\":70,\"d\":1,\"t\":222222333}],\"t\":[\"tag-1\",\"tag-2\"],\"ufs\":{\"sp\":5}}" } + let(:empty_body_usage) { "{\"lS\":{\"sp\":0,\"se\":0,\"im\":0,\"ic\":0,\"ev\":0,\"te\":0,\"to\":0},\"mL\":{\"t\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ts\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tc\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tcs\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"tr\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"mE\":{\"t\":0,\"ts\":0,\"tc\":0,\"tcs\":0,\"tr\":0},\"hE\":{\"sp\":{},\"se\":{},\"im\":{},\"ic\":{},\"ev\":{},\"te\":{},\"to\":{}},\"hL\":{\"sp\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"se\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"im\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ic\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"ev\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"te\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"to\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},\"tR\":0,\"aR\":0,\"iQ\":0,\"iDe\":0,\"iDr\":0,\"spC\":0,\"seC\":0,\"skC\":0,\"sL\":0,\"eQ\":0,\"eD\":0,\"sE\":[],\"t\":[],\"ufs\":{\"sp\":0}}" } let(:body_custom_config) { "{\"oM\":0,\"sE\":true,\"st\":\"memory\",\"rR\":{\"sp\":100,\"se\":110,\"im\":120,\"ev\":130,\"te\":140},\"iQ\":5000,\"eQ\":500,\"iM\":0,\"uO\":{\"s\":true,\"e\":true,\"a\":true,\"st\":false,\"t\":false},\"iL\":false,\"hP\":false,\"aF\":1,\"rF\":1,\"tR\":100,\"bT\":2,\"nR\":1,\"t\":[],\"i\":null}" } let(:body_default_config) { "{\"oM\":0,\"sE\":true,\"st\":\"memory\",\"rR\":{\"sp\":60,\"se\":60,\"im\":300,\"ev\":60,\"te\":3600},\"iQ\":5000,\"eQ\":500,\"iM\":0,\"uO\":{\"s\":false,\"e\":false,\"a\":false,\"st\":false,\"t\":false},\"iL\":false,\"hP\":false,\"aF\":1,\"rF\":1,\"tR\":500,\"bT\":0,\"nR\":0,\"t\":[],\"i\":null}" } let(:body_proxy_config) { "{\"oM\":0,\"sE\":true,\"st\":\"memory\",\"rR\":{\"sp\":60,\"se\":60,\"im\":300,\"ev\":60,\"te\":3600},\"iQ\":5000,\"eQ\":500,\"iM\":0,\"uO\":{\"s\":false,\"e\":false,\"a\":false,\"st\":false,\"t\":false},\"iL\":false,\"hP\":true,\"aF\":1,\"rF\":1,\"tR\":500,\"bT\":0,\"nR\":0,\"t\":[],\"i\":null}" } @@ -100,6 +100,11 @@ runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::SYNC_MODE, 0, 222_222_333) runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::SYNC_MODE, 1, 222_222_333) runtime_producer.record_session_length(444_555) + runtime_producer.record_updates_from_sse(SplitIoClient::Telemetry::Domain::Constants::SPLITS) + runtime_producer.record_updates_from_sse(SplitIoClient::Telemetry::Domain::Constants::SPLITS) + runtime_producer.record_updates_from_sse(SplitIoClient::Telemetry::Domain::Constants::SPLITS) + runtime_producer.record_updates_from_sse(SplitIoClient::Telemetry::Domain::Constants::SPLITS) + runtime_producer.record_updates_from_sse(SplitIoClient::Telemetry::Domain::Constants::SPLITS) evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 1) evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 3) evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 2) diff --git a/spec/test_data/regexp/data.txt b/spec/test_data/regexp/data.txt index d776a132..973570c9 100644 --- a/spec/test_data/regexp/data.txt +++ b/spec/test_data/regexp/data.txt @@ -115,8 +115,6 @@ perl\B#perl stuff#false ^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$#john@doe.com#true ^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$#john@doe.something#false ^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$#johndoe.sg#false -^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$#http://split.io/about#true -^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$#http://google.com/some/file!.html#false ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$#73.60.124.136#true ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$#256.60.124.136#false ^\d+$#123#true diff --git a/splitclient-rb.gemspec b/splitclient-rb.gemspec index fb6a32c8..a8adca6a 100644 --- a/splitclient-rb.gemspec +++ b/splitclient-rb.gemspec @@ -37,6 +37,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'allocation_stats', '~> 0.1' spec.add_development_dependency 'bundler', '~> 2.2' + spec.add_development_dependency 'byebug', '~> 11.1' spec.add_development_dependency 'pry', '~> 0.14' spec.add_development_dependency 'pry-nav', '~> 1.0' spec.add_development_dependency 'rake', '~> 13.0'