splitclient-rb 8.4.0 → 8.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +9 -2
  3. data/CHANGES.txt +24 -0
  4. data/LICENSE +169 -13
  5. data/NOTICE.txt +5 -0
  6. data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +9 -7
  7. data/lib/splitclient-rb/cache/filter/bloom_filter.rb +10 -6
  8. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +1 -0
  9. data/lib/splitclient-rb/cache/repositories/rule_based_segments_repository.rb +136 -0
  10. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +21 -2
  11. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +42 -12
  12. data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +24 -10
  13. data/lib/splitclient-rb/cache/stores/localhost_split_builder.rb +2 -1
  14. data/lib/splitclient-rb/clients/split_client.rb +146 -62
  15. data/lib/splitclient-rb/engine/api/client.rb +8 -0
  16. data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +1 -0
  17. data/lib/splitclient-rb/engine/api/splits.rb +100 -24
  18. data/lib/splitclient-rb/engine/auth_api_client.rb +3 -3
  19. data/lib/splitclient-rb/engine/common/impressions_manager.rb +56 -30
  20. data/lib/splitclient-rb/engine/events/events_delivery.rb +20 -0
  21. data/lib/splitclient-rb/engine/events/events_manager.rb +194 -0
  22. data/lib/splitclient-rb/engine/events/events_manager_config.rb +96 -0
  23. data/lib/splitclient-rb/engine/events/events_task.rb +50 -0
  24. data/lib/splitclient-rb/engine/events/noop_events_queue.rb +13 -0
  25. data/lib/splitclient-rb/engine/fallback_treatment_calculator.rb +48 -0
  26. data/lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb +58 -11
  27. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +3 -1
  28. data/lib/splitclient-rb/engine/matchers/prerequisites_matcher.rb +31 -0
  29. data/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +78 -0
  30. data/lib/splitclient-rb/engine/models/evaluation_options.rb +9 -0
  31. data/lib/splitclient-rb/engine/models/event_active_subscriptions.rb +14 -0
  32. data/lib/splitclient-rb/engine/models/events_metadata.rb +10 -0
  33. data/lib/splitclient-rb/engine/models/fallback_treatment.rb +11 -0
  34. data/lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb +36 -0
  35. data/lib/splitclient-rb/engine/models/label.rb +1 -0
  36. data/lib/splitclient-rb/engine/models/sdk_event.rb +4 -0
  37. data/lib/splitclient-rb/engine/models/sdk_event_type.rb +4 -0
  38. data/lib/splitclient-rb/engine/models/sdk_internal_event.rb +8 -0
  39. data/lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb +14 -0
  40. data/lib/splitclient-rb/engine/models/segment_type.rb +4 -0
  41. data/lib/splitclient-rb/engine/models/split_http_response.rb +19 -0
  42. data/lib/splitclient-rb/engine/models/valid_sdk_event.rb +14 -0
  43. data/lib/splitclient-rb/engine/parser/condition.rb +9 -0
  44. data/lib/splitclient-rb/engine/parser/evaluator.rb +24 -30
  45. data/lib/splitclient-rb/engine/status_manager.rb +7 -1
  46. data/lib/splitclient-rb/engine/sync_manager.rb +6 -6
  47. data/lib/splitclient-rb/engine/synchronizer.rb +37 -17
  48. data/lib/splitclient-rb/helpers/evaluator_helper.rb +37 -0
  49. data/lib/splitclient-rb/helpers/repository_helper.rb +39 -1
  50. data/lib/splitclient-rb/helpers/util.rb +12 -3
  51. data/lib/splitclient-rb/managers/split_manager.rb +2 -1
  52. data/lib/splitclient-rb/spec.rb +1 -1
  53. data/lib/splitclient-rb/split_config.rb +45 -5
  54. data/lib/splitclient-rb/split_factory.rb +27 -21
  55. data/lib/splitclient-rb/sse/event_source/client.rb +86 -29
  56. data/lib/splitclient-rb/sse/event_source/event_parser.rb +2 -2
  57. data/lib/splitclient-rb/sse/event_source/event_types.rb +1 -0
  58. data/lib/splitclient-rb/sse/notification_manager_keeper.rb +3 -3
  59. data/lib/splitclient-rb/sse/notification_processor.rb +3 -1
  60. data/lib/splitclient-rb/sse/workers/segments_worker.rb +4 -4
  61. data/lib/splitclient-rb/sse/workers/splits_worker.rb +63 -24
  62. data/lib/splitclient-rb/utilitites.rb +6 -10
  63. data/lib/splitclient-rb/validators.rb +56 -25
  64. data/lib/splitclient-rb/version.rb +1 -1
  65. data/lib/splitclient-rb.rb +22 -0
  66. data/sonar-project.properties +1 -0
  67. data/splitclient-rb.gemspec +3 -4
  68. metadata +32 -38
@@ -15,6 +15,7 @@ module SplitIoClient
15
15
  )
16
16
  @splits_repository = repositories[:splits]
17
17
  @segments_repository = repositories[:segments]
18
+ @rule_based_segments_repository = repositories[:rule_based_segments]
18
19
  @impressions_repository = repositories[:impressions]
19
20
  @events_repository = repositories[:events]
20
21
  @config = config
@@ -48,7 +49,7 @@ module SplitIoClient
48
49
  events_sender
49
50
  start_telemetry_sync_task
50
51
  end
51
-
52
+
52
53
  impressions_count_sender
53
54
  start_unique_keys_tracker_task
54
55
  end
@@ -63,12 +64,12 @@ module SplitIoClient
63
64
  @segment_fetcher.stop_segments_thread
64
65
  end
65
66
 
66
- def fetch_splits(target_change_number)
67
- return if target_change_number <= @splits_repository.get_change_number.to_i
67
+ def fetch_splits(target_change_number, rbs_target_change_number)
68
+ return if check_exit_conditions(target_change_number, rbs_target_change_number)
68
69
 
69
70
  fetch_options = { cache_control_headers: true, till: nil }
70
71
 
71
- result = attempt_splits_sync(target_change_number,
72
+ result = attempt_splits_sync(target_change_number, rbs_target_change_number,
72
73
  fetch_options,
73
74
  @config.on_demand_fetch_max_retries,
74
75
  @config.on_demand_fetch_retry_delay_seconds,
@@ -82,8 +83,13 @@ module SplitIoClient
82
83
  return
83
84
  end
84
85
 
85
- fetch_options[:till] = target_change_number
86
- result = attempt_splits_sync(target_change_number,
86
+ if target_change_number != 0
87
+ fetch_options[:till] = target_change_number
88
+ else
89
+ fetch_options[:till] = rbs_target_change_number
90
+ end
91
+
92
+ result = attempt_splits_sync(target_change_number, rbs_target_change_number,
87
93
  fetch_options,
88
94
  ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES,
89
95
  nil,
@@ -91,12 +97,7 @@ module SplitIoClient
91
97
 
92
98
  attempts = ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES - result[:remaining_attempts]
93
99
 
94
- if result[:success]
95
- @segment_fetcher.fetch_segments_if_not_exists(result[:segment_names], true) unless result[:segment_names].empty?
96
- @config.logger.debug("Refresh completed bypassing the CDN in #{attempts} attempts.") if @config.debug_enabled
97
- else
98
- @config.logger.debug("No changes fetched after #{attempts} attempts with CDN bypassed.") if @config.debug_enabled
99
- end
100
+ process_result(result, attempts)
100
101
  rescue StandardError => e
101
102
  @config.log_found_exception(__method__.to_s, e)
102
103
  end
@@ -139,6 +140,15 @@ module SplitIoClient
139
140
 
140
141
  private
141
142
 
143
+ def process_result(result, attempts)
144
+ if result[:success]
145
+ @segment_fetcher.fetch_segments_if_not_exists(result[:segment_names], true) unless result[:segment_names].empty?
146
+ @config.logger.debug("Refresh completed bypassing the CDN in #{attempts} attempts.") if @config.debug_enabled
147
+ else
148
+ @config.logger.debug("No changes fetched after #{attempts} attempts with CDN bypassed.") if @config.debug_enabled
149
+ end
150
+ end
151
+
142
152
  def attempt_segment_sync(name, target_cn, fetch_options, max_retries, retry_delay_seconds, with_backoff)
143
153
  remaining_attempts = max_retries
144
154
  @segments_sync_backoff.reset
@@ -156,7 +166,7 @@ module SplitIoClient
156
166
  end
157
167
  end
158
168
 
159
- def attempt_splits_sync(target_cn, fetch_options, max_retries, retry_delay_seconds, with_backoff)
169
+ def attempt_splits_sync(target_cn, rbs_target_cn, fetch_options, max_retries, retry_delay_seconds, with_backoff)
160
170
  remaining_attempts = max_retries
161
171
  @splits_sync_backoff.reset
162
172
 
@@ -165,7 +175,7 @@ module SplitIoClient
165
175
 
166
176
  result = @split_fetcher.fetch_splits(fetch_options)
167
177
 
168
- return sync_result(true, remaining_attempts, result[:segment_names]) if target_cn <= @splits_repository.get_change_number
178
+ return sync_result(true, remaining_attempts, result[:segment_names]) if check_exit_conditions(target_cn, rbs_target_cn)
169
179
  return sync_result(false, remaining_attempts, result[:segment_names]) if remaining_attempts <= 0
170
180
 
171
181
  delay = with_backoff ? @splits_sync_backoff.interval : retry_delay_seconds
@@ -175,7 +185,7 @@ module SplitIoClient
175
185
 
176
186
  # Starts thread which loops constantly and sends impressions to the Split API
177
187
  def impressions_sender
178
- ImpressionsSender.new(@impressions_repository, @config, @impressions_api).call unless @config.impressions_mode == :none
188
+ ImpressionsSender.new(@impressions_repository, @config, @impressions_api).call
179
189
  end
180
190
 
181
191
  # Starts thread which loops constantly and sends events to the Split API
@@ -185,7 +195,7 @@ module SplitIoClient
185
195
 
186
196
  # Starts thread which loops constantly and sends impressions count to the Split API
187
197
  def impressions_count_sender
188
- ImpressionsCountSender.new(@config, @impression_counter, @impressions_sender_adapter).call unless @config.impressions_mode == :debug
198
+ ImpressionsCountSender.new(@config, @impression_counter, @impressions_sender_adapter).call
189
199
  end
190
200
 
191
201
  def start_telemetry_sync_task
@@ -203,9 +213,19 @@ module SplitIoClient
203
213
  def sync_splits_and_segments
204
214
  @config.logger.debug('Synchronizing feature flags and segments ...') if @config.debug_enabled
205
215
  splits_result = @split_fetcher.fetch_splits
206
-
216
+
207
217
  splits_result[:success] && @segment_fetcher.fetch_segments
208
218
  end
219
+
220
+ def check_exit_conditions(target_change_number, rbs_target_change_number)
221
+ return true if rbs_target_change_number == 0 and target_change_number == 0
222
+
223
+ return target_change_number <= @splits_repository.get_change_number.to_i if rbs_target_change_number == 0
224
+
225
+ return rbs_target_change_number <= @rule_based_segments_repository.get_change_number.to_i if target_change_number == 0
226
+
227
+ return (target_change_number <= @splits_repository.get_change_number.to_i and rbs_target_change_number <= @rule_based_segments_repository.get_change_number.to_i)
228
+ end
209
229
  end
210
230
  end
211
231
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ module Helpers
5
+ class EvaluatorHelper
6
+ def self.matcher_type(condition, segments_repository, rb_segment_repository)
7
+ matchers = []
8
+ segments_repository.adapter.pipelined do
9
+ condition.matchers.each do |matcher|
10
+ matchers << if matcher[:negate]
11
+ condition.negation_matcher(matcher_instance(matcher[:matcherType], condition,
12
+ matcher, segments_repository,
13
+ rb_segment_repository))
14
+ else
15
+ matcher_instance(matcher[:matcherType], condition, matcher, segments_repository, rb_segment_repository)
16
+ end
17
+ end
18
+ end
19
+ final_matcher = condition.create_condition_matcher(matchers)
20
+
21
+ if final_matcher.nil?
22
+ config.logger.error('Invalid matcher type')
23
+ else
24
+ final_matcher
25
+ end
26
+ final_matcher
27
+ end
28
+
29
+ def self.matcher_instance(type, condition, matcher, segments_repository, rb_segment_repository)
30
+ condition.send(
31
+ "matcher_#{type.downcase}",
32
+ matcher: matcher, segments_repository: segments_repository, rule_based_segments_repository: rb_segment_repository
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,7 +3,7 @@
3
3
  module SplitIoClient
4
4
  module Helpers
5
5
  class RepositoryHelper
6
- def self.update_feature_flag_repository(feature_flag_repository, feature_flags, change_number, config)
6
+ def self.update_feature_flag_repository(feature_flag_repository, feature_flags, change_number, config, clear_storage)
7
7
  to_add = []
8
8
  to_delete = []
9
9
  feature_flags.each do |feature_flag|
@@ -13,11 +13,49 @@ module SplitIoClient
13
13
  next
14
14
  end
15
15
 
16
+ feature_flag = check_missing_elements(feature_flag, config)
17
+
16
18
  config.logger.debug("storing feature flag (#{feature_flag[:name]})") if config.debug_enabled
17
19
  to_add.push(feature_flag)
18
20
  end
21
+ feature_flag_repository.clear if clear_storage
19
22
  feature_flag_repository.update(to_add, to_delete, change_number)
20
23
  end
24
+
25
+ def self.check_missing_elements(feature_flag, config)
26
+ unless feature_flag.key?(:impressionsDisabled)
27
+ feature_flag[:impressionsDisabled] = false
28
+ if config.debug_enabled
29
+ config.logger.debug("feature flag (#{feature_flag[:name]}) does not have impressionsDisabled field, setting it to false")
30
+ end
31
+ end
32
+
33
+ unless feature_flag.key?(:prerequisites)
34
+ feature_flag[:prerequisites] = []
35
+ if config.debug_enabled
36
+ config.logger.debug("feature flag (#{feature_flag[:name]}) does not have prerequisites field, setting it to empty array")
37
+ end
38
+ end
39
+
40
+ feature_flag
41
+ end
42
+
43
+ def self.update_rule_based_segment_repository(rule_based_segment_repository, rule_based_segments, change_number, config)
44
+ to_add = []
45
+ to_delete = []
46
+ rule_based_segments.each do |rule_based_segment|
47
+ if Engine::Models::Split.archived?(rule_based_segment)
48
+ config.logger.debug("removing rule based segment from store(#{rule_based_segment})") if config.debug_enabled
49
+ to_delete.push(rule_based_segment)
50
+ next
51
+ end
52
+
53
+ config.logger.debug("storing rule based segment (#{rule_based_segment[:name]})") if config.debug_enabled
54
+ to_add.push(rule_based_segment)
55
+ end
56
+
57
+ rule_based_segment_repository.update(to_add, to_delete, change_number)
58
+ end
21
59
  end
22
60
  end
23
61
  end
@@ -3,15 +3,24 @@
3
3
  module SplitIoClient
4
4
  module Helpers
5
5
  class Util
6
- def self.segment_names_by_feature_flag(feature_flag)
7
- feature_flag[:conditions].each_with_object(Set.new) do |condition, names|
6
+ def self.segment_names_by_object(object, matcher_type)
7
+ object[:conditions].each_with_object(Set.new) do |condition, names|
8
8
  condition[:matcherGroup][:matchers].each do |matcher|
9
- next if matcher[:userDefinedSegmentMatcherData].nil?
9
+ next if matcher[:userDefinedSegmentMatcherData].nil? || matcher[:matcherType] != matcher_type
10
10
 
11
11
  names << matcher[:userDefinedSegmentMatcherData][:segmentName]
12
12
  end
13
13
  end
14
14
  end
15
+
16
+ def self.segment_names_in_rb_segment(object, matcher_type)
17
+ names = Set.new
18
+ names.merge segment_names_by_object(object, matcher_type)
19
+ object[:excluded][:segments].each do |segment|
20
+ names.add(segment[:name]) if segment[:type] == SplitIoClient::Engine::Models::SegmentType::STANDARD
21
+ end
22
+ names
23
+ end
15
24
  end
16
25
  end
17
26
  end
@@ -107,7 +107,8 @@ module SplitIoClient
107
107
  change_number: split[:changeNumber],
108
108
  configs: split[:configurations] || {},
109
109
  sets: split[:sets] || [],
110
- default_treatment: split[:defaultTreatment]
110
+ default_treatment: split[:defaultTreatment],
111
+ impressions_disabled: split[:impressionsDisabled]
111
112
  }
112
113
  end
113
114
 
@@ -3,7 +3,7 @@
3
3
  module SplitIoClient
4
4
  module Spec
5
5
  class FeatureFlags
6
- SPEC_VERSION = "1.1"
6
+ SPEC_VERSION = "1.3"
7
7
  end
8
8
  end
9
9
  end
@@ -112,7 +112,7 @@ module SplitIoClient
112
112
  @telemetry_service_url = opts[:telemetry_service_url] || SplitConfig.default_telemetry_service_url
113
113
 
114
114
  @unique_keys_refresh_rate = SplitConfig.default_unique_keys_refresh_rate(@cache_adapter)
115
- @unique_keys_cache_max_size = SplitConfig.default_unique_keys_cache_max_size
115
+ # @unique_keys_cache_max_size = SplitConfig.default_unique_keys_cache_max_size
116
116
  @unique_keys_bulk_size = SplitConfig.default_unique_keys_bulk_size(@cache_adapter)
117
117
 
118
118
  @counter_refresh_rate = SplitConfig.default_counter_refresh_rate(@cache_adapter)
@@ -123,6 +123,8 @@ module SplitIoClient
123
123
  @on_demand_fetch_max_retries = SplitConfig.default_on_demand_fetch_max_retries
124
124
 
125
125
  @flag_sets_filter = SplitConfig.sanitize_flag_set_filter(opts[:flag_sets_filter], @split_validator, opts[:cache_adapter], @logger)
126
+
127
+ @fallback_treatments_configuration = SplitConfig.sanitize_fallback_config(opts[:fallback_treatments], @split_validator, @logger)
126
128
  startup_log
127
129
  end
128
130
 
@@ -292,7 +294,7 @@ module SplitIoClient
292
294
  attr_accessor :on_demand_fetch_max_retries
293
295
 
294
296
  attr_accessor :unique_keys_refresh_rate
295
- attr_accessor :unique_keys_cache_max_size
297
+ #attr_accessor :unique_keys_cache_max_size
296
298
  attr_accessor :unique_keys_bulk_size
297
299
 
298
300
  attr_accessor :counter_refresh_rate
@@ -303,6 +305,8 @@ module SplitIoClient
303
305
  # @return [Array]
304
306
  attr_accessor :flag_sets_filter
305
307
 
308
+ attr_accessor :fallback_treatments_configuration
309
+
306
310
  def self.default_counter_refresh_rate(adapter)
307
311
  return 300 if adapter == :redis # Send bulk impressions count - Refresh rate: 5 min.
308
312
 
@@ -498,9 +502,9 @@ module SplitIoClient
498
502
  900
499
503
  end
500
504
 
501
- def self.default_unique_keys_cache_max_size
502
- 30000
503
- end
505
+ # def self.default_unique_keys_cache_max_size
506
+ # 30000
507
+ # end
504
508
 
505
509
  def self.default_unique_keys_bulk_size(adapter)
506
510
  return 2000 if adapter == :redis
@@ -645,6 +649,10 @@ module SplitIoClient
645
649
  @mode.equal?(:consumer)
646
650
  end
647
651
 
652
+ def sdk_url_overriden?
653
+ return @base_uri != SplitConfig.default_base_uri
654
+ end
655
+
648
656
  #
649
657
  # gets the hostname where the sdk gem is running
650
658
  #
@@ -693,5 +701,37 @@ module SplitIoClient
693
701
 
694
702
  return ''.freeze
695
703
  end
704
+
705
+ def self.sanitize_fallback_config(fallback_config, validator, logger)
706
+ return fallback_config if fallback_config.nil?
707
+
708
+ processed = Engine::Models::FallbackTreatmentsConfiguration.new
709
+ if !fallback_config.is_a?(Engine::Models::FallbackTreatmentsConfiguration)
710
+ logger.warn('Config: fallbackTreatments parameter should be of `FallbackTreatmentsConfiguration` class.')
711
+ return processed
712
+ end
713
+
714
+ sanitized_global_fallback_treatment = fallback_config.global_fallback_treatment
715
+ if !fallback_config.global_fallback_treatment.nil? && !validator.validate_fallback_treatment('Config', fallback_config.global_fallback_treatment)
716
+ logger.warn('Config: global fallbacktreatment parameter is discarded.')
717
+ sanitized_global_fallback_treatment = nil
718
+ end
719
+
720
+ sanitized_flag_fallback_treatments = nil
721
+ if !fallback_config.by_flag_fallback_treatment.nil? && fallback_config.by_flag_fallback_treatment.is_a?(Hash)
722
+ sanitized_flag_fallback_treatments = Hash.new
723
+ for feature_name in fallback_config.by_flag_fallback_treatment.keys()
724
+ if !validator.valid_split_name?('Config', feature_name) || !validator.validate_fallback_treatment('Config', fallback_config.by_flag_fallback_treatment[feature_name])
725
+ logger.warn("Config: fallback treatment parameter for feature flag #{feature_name} is discarded.")
726
+ next
727
+ end
728
+
729
+ sanitized_flag_fallback_treatments[feature_name] = fallback_config.by_flag_fallback_treatment[feature_name]
730
+ end
731
+ end
732
+ processed = Engine::Models::FallbackTreatmentsConfiguration.new(sanitized_global_fallback_treatment, sanitized_flag_fallback_treatments)
733
+
734
+ processed
735
+ end
696
736
  end
697
737
  end
@@ -45,6 +45,7 @@ module SplitIoClient
45
45
 
46
46
  register_factory
47
47
 
48
+ build_events_manager
48
49
  build_telemetry_components
49
50
  build_flag_sets_filter
50
51
  build_repositories
@@ -53,13 +54,13 @@ module SplitIoClient
53
54
  build_unique_keys_tracker
54
55
  build_impressions_components
55
56
 
56
- @status_manager = Engine::StatusManager.new(@config)
57
+ @status_manager = Engine::StatusManager.new(@config, @internal_events_queue)
57
58
  @split_validator = SplitIoClient::Validators.new(@config)
58
- @evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @config)
59
+ @evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @rule_based_segment_repository, @config)
59
60
 
60
61
  start!
61
-
62
- @client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator)
62
+ fallback_treatment_calculator = SplitIoClient::Engine::FallbackTreatmentCalculator.new(@config.fallback_treatments_configuration)
63
+ @client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator, fallback_treatment_calculator, @events_manager)
63
64
  @manager = SplitManager.new(@splits_repository, @status_manager, @config)
64
65
  end
65
66
 
@@ -154,6 +155,7 @@ module SplitIoClient
154
155
  segments: @segments_repository,
155
156
  impressions: @impressions_repository,
156
157
  events: @events_repository,
158
+ rule_based_segments: @rule_based_segment_repository
157
159
  }
158
160
  end
159
161
 
@@ -178,7 +180,7 @@ module SplitIoClient
178
180
  end
179
181
 
180
182
  def build_fetchers
181
- @split_fetcher = SplitFetcher.new(@splits_repository, @api_key, @config, @runtime_producer)
183
+ @split_fetcher = SplitFetcher.new(@splits_repository, @rule_based_segment_repository, @api_key, @config, @runtime_producer)
182
184
  @segment_fetcher = SegmentFetcher.new(@segments_repository, @api_key, @config, @runtime_producer)
183
185
  end
184
186
 
@@ -198,7 +200,7 @@ module SplitIoClient
198
200
 
199
201
  def build_streaming_components
200
202
  @push_status_queue = Queue.new
201
- splits_worker = SSE::Workers::SplitsWorker.new(@synchronizer, @config, @splits_repository, @runtime_producer, @segment_fetcher)
203
+ splits_worker = SSE::Workers::SplitsWorker.new(@synchronizer, @config, @splits_repository, @runtime_producer, @segment_fetcher, @rule_based_segment_repository)
202
204
  segments_worker = SSE::Workers::SegmentsWorker.new(@synchronizer, @config, @segments_repository)
203
205
  notification_manager_keeper = SSE::NotificationManagerKeeper.new(@config, @runtime_producer, @push_status_queue)
204
206
  notification_processor = SSE::NotificationProcessor.new(@config, splits_worker, segments_worker)
@@ -218,8 +220,9 @@ module SplitIoClient
218
220
  else
219
221
  @flag_sets_repository = SplitIoClient::Cache::Repositories::MemoryFlagSetsRepository.new(@config.flag_sets_filter)
220
222
  end
221
- @splits_repository = SplitsRepository.new(@config, @flag_sets_repository, @flag_sets_filter)
222
- @segments_repository = SegmentsRepository.new(@config)
223
+ @splits_repository = SplitsRepository.new(@config, @flag_sets_repository, @flag_sets_filter, @internal_events_queue)
224
+ @segments_repository = SegmentsRepository.new(@config, @internal_events_queue)
225
+ @rule_based_segment_repository = RuleBasedSegmentsRepository.new(@config, @internal_events_queue)
223
226
  @impressions_repository = ImpressionsRepository.new(@config)
224
227
  @events_repository = EventsRepository.new(@config, @api_key, @runtime_producer)
225
228
  end
@@ -230,11 +233,6 @@ module SplitIoClient
230
233
  end
231
234
 
232
235
  def build_unique_keys_tracker
233
- if @config.impressions_mode != :none
234
- @unique_keys_tracker = Engine::Impressions::NoopUniqueKeysTracker.new
235
- return
236
- end
237
-
238
236
  bf = Cache::Filter::BloomFilter.new(30_000_000)
239
237
  filter_adapter = Cache::Filter::FilterAdapter.new(@config, bf)
240
238
  cache = Concurrent::Hash.new
@@ -242,8 +240,7 @@ module SplitIoClient
242
240
  end
243
241
 
244
242
  def build_impressions_observer
245
- if (@config.cache_adapter == :redis && @config.impressions_mode != :optimized) ||
246
- (@config.cache_adapter == :memory && @config.impressions_mode == :none)
243
+ if (@config.cache_adapter == :redis && @config.impressions_mode != :optimized)
247
244
  @impression_observer = Observers::NoopImpressionObserver.new
248
245
  else
249
246
  @impression_observer = Observers::ImpressionObserver.new
@@ -251,12 +248,7 @@ module SplitIoClient
251
248
  end
252
249
 
253
250
  def build_impression_counter
254
- case @config.impressions_mode
255
- when :debug
256
- @impression_counter = Engine::Common::NoopImpressionCounter.new
257
- else
258
- @impression_counter = Engine::Common::ImpressionCounter.new
259
- end
251
+ @impression_counter = Engine::Common::ImpressionCounter.new
260
252
  end
261
253
 
262
254
  def build_impressions_sender_adapter
@@ -274,5 +266,19 @@ module SplitIoClient
274
266
  def build_flag_sets_filter
275
267
  @flag_sets_filter = SplitIoClient::Cache::Filter::FlagSetsFilter.new(@config.flag_sets_filter)
276
268
  end
269
+
270
+ def build_events_manager
271
+ @events_manager = Engine::Events::EventsManager.new(Engine::Events::EventsManagerConfig.new,
272
+ Engine::Events::EventsDelivery.new(@config),
273
+ @config)
274
+ if @config.consumer?
275
+ @internal_events_queue = Engine::Events::NoOpEventsQueue.new
276
+ return
277
+ end
278
+
279
+ @internal_events_queue = Queue.new
280
+ @events_task = Engine::Events::EventsTask.new(@events_manager.method(:notify_internal_event), @internal_events_queue, @config)
281
+ @events_task.start
282
+ end
277
283
  end
278
284
  end