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
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ module Engine
5
+ module Events
6
+ class NoOpEventsQueue
7
+ def push(sdk_event)
8
+ # do nothing
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ module Engine
5
+ class FallbackTreatmentCalculator
6
+ attr_accessor :fallback_treatments_configuration, :label_prefix
7
+
8
+ def initialize(fallback_treatment_configuration)
9
+ @label_prefix = 'fallback - '
10
+ @fallback_treatments_configuration = fallback_treatment_configuration
11
+ end
12
+
13
+ def resolve(flag_name, label)
14
+ default_fallback_treatment = Engine::Models::FallbackTreatment.new(
15
+ Engine::Models::Treatment::CONTROL,
16
+ nil,
17
+ label
18
+ )
19
+ return default_fallback_treatment if @fallback_treatments_configuration.nil?
20
+
21
+ if !@fallback_treatments_configuration.by_flag_fallback_treatment.nil? \
22
+ && !@fallback_treatments_configuration.by_flag_fallback_treatment.fetch(flag_name, nil).nil?
23
+ return copy_with_label(
24
+ @fallback_treatments_configuration.by_flag_fallback_treatment[flag_name],
25
+ resolve_label(label)
26
+ )
27
+ end
28
+
29
+ return copy_with_label(@fallback_treatments_configuration.global_fallback_treatment, resolve_label(label)) \
30
+ unless @fallback_treatments_configuration.global_fallback_treatment.nil?
31
+
32
+ default_fallback_treatment
33
+ end
34
+
35
+ private
36
+
37
+ def resolve_label(label)
38
+ return nil if label.nil?
39
+
40
+ @label_prefix + label
41
+ end
42
+
43
+ def copy_with_label(fallback_treatment, label)
44
+ Engine::Models::FallbackTreatment.new(fallback_treatment.treatment, fallback_treatment.config, label)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -14,9 +14,9 @@ module SplitIoClient
14
14
  @filter_adapter = filter_adapter
15
15
  @sender_adapter = sender_adapter
16
16
  @cache = cache
17
- @cache_max_size = config.unique_keys_cache_max_size
18
17
  @max_bulk_size = config.unique_keys_bulk_size
19
18
  @semaphore = Mutex.new
19
+ @keys_size = 0
20
20
  end
21
21
 
22
22
  def call
@@ -30,8 +30,9 @@ module SplitIoClient
30
30
  @filter_adapter.add(feature_name, key)
31
31
 
32
32
  add_or_update(feature_name, key)
33
+ @keys_size += 1
33
34
 
34
- send_bulk_data if @cache.size >= @cache_max_size
35
+ send_bulk_data if @keys_size >= @max_bulk_size
35
36
 
36
37
  true
37
38
  rescue StandardError => e
@@ -70,27 +71,73 @@ module SplitIoClient
70
71
  end
71
72
  end
72
73
 
74
+ def clear_cache
75
+ uniques = @cache.clone
76
+ keys_size = @keys_size
77
+ @cache.clear
78
+ @keys_size = 0
79
+
80
+ [uniques, keys_size]
81
+ end
82
+
73
83
  def send_bulk_data
74
84
  @semaphore.synchronize do
75
85
  return if @cache.empty?
76
86
 
77
- uniques = @cache.clone
78
- @cache.clear
79
-
80
- if uniques.size <= @max_bulk_size
87
+ uniques, keys_size = clear_cache
88
+ if keys_size <= @max_bulk_size
81
89
  @sender_adapter.record_uniques_key(uniques)
82
90
  return
83
- end
84
-
85
- bulks = SplitIoClient::Utilities.split_bulk_to_send(uniques, uniques.size / @max_bulk_size)
86
91
 
87
- bulks.each do |b|
88
- @sender_adapter.record_uniques_key(b)
89
92
  end
93
+ bulks = flatten_bulks(uniques)
94
+ bulks_to_post = group_bulks_by_max_size(bulks)
95
+ @sender_adapter.record_uniques_key(bulks_to_post)
90
96
  end
91
97
  rescue StandardError => e
92
98
  @config.log_found_exception(__method__.to_s, e)
93
99
  end
100
+
101
+ def group_bulks_by_max_size(bulks)
102
+ current_size = 0
103
+ bulks_to_post = Concurrent::Hash.new
104
+ bulks.each do |bulk|
105
+ key, value = bulk.first
106
+ if (value.size + current_size) > @max_bulk_size
107
+ @sender_adapter.record_uniques_key(bulks_to_post)
108
+ bulks_to_post = Concurrent::Hash.new
109
+ current_size = 0
110
+ end
111
+ bulks_to_post[key] = value
112
+ current_size += value.size
113
+ end
114
+
115
+ bulks_to_post
116
+ end
117
+
118
+ def flatten_bulks(uniques)
119
+ bulks = []
120
+ uniques.each_key do |unique_key|
121
+ bulks += check_keys_and_split_to_bulks(uniques[unique_key], unique_key)
122
+ end
123
+
124
+ bulks
125
+ end
126
+
127
+ def check_keys_and_split_to_bulks(value, key)
128
+ unique_updated = []
129
+ if value.size > @max_bulk_size
130
+ sub_bulks = SplitIoClient::Utilities.split_bulk_to_send(value, @max_bulk_size)
131
+ sub_bulks.each do |sub_bulk|
132
+ unique_updated << { key => sub_bulk.to_set }
133
+ end
134
+ return unique_updated
135
+
136
+ end
137
+ unique_updated << { key => value }
138
+
139
+ unique_updated
140
+ end
94
141
  end
95
142
  end
96
143
  end
@@ -56,7 +56,9 @@ module SplitIoClient
56
56
 
57
57
  @matchers.all? do |matcher|
58
58
  if match_with_key?(matcher)
59
- matcher.match?(value: args[:matching_key])
59
+ key = args[:value]
60
+ key = args[:matching_key] unless args[:matching_key].nil?
61
+ matcher.match?(value: key)
60
62
  else
61
63
  matcher.match?(args)
62
64
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ class PrerequisitesMatcher
5
+ def initialize(prerequisites, logger)
6
+ @prerequisites = prerequisites
7
+ @logger = logger
8
+ end
9
+
10
+ def match?(args)
11
+ keys = { matching_key: args[:matching_key], bucketing_key: args[:bucketing_key] }
12
+
13
+ match = true
14
+ @prerequisites.each do |prerequisite|
15
+ evaluate = args[:evaluator].evaluate_feature_flag(keys, prerequisite[:n], args[:attributes])
16
+ next if prerequisite[:ts].include?(evaluate[:treatment])
17
+
18
+ @logger.log_if_debug("[PrerequisitesMatcher] feature flag #{prerequisite[:n]} evaluated to #{evaluate[:treatment]} \
19
+ that does not exist in prerequisited treatments.")
20
+ match = false
21
+ break
22
+ end
23
+
24
+ match
25
+ end
26
+
27
+ def string_type?
28
+ false
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ #
5
+ # class to implement the user defined matcher
6
+ #
7
+ class RuleBasedSegmentMatcher < Matcher
8
+ MATCHER_TYPE = 'IN_RULE_BASED_SEGMENT'
9
+
10
+ def initialize(segments_repository, rule_based_segments_repository, segment_name, config)
11
+ super(config.logger)
12
+ @rule_based_segments_repository = rule_based_segments_repository
13
+ @segments_repository = segments_repository
14
+ @segment_name = segment_name
15
+ @config = config
16
+ end
17
+
18
+ #
19
+ # evaluates if the key matches the matcher
20
+ #
21
+ # @param key [string] key value to be matched
22
+ #
23
+ # @return [boolean] evaluation of the key against the segment
24
+ def match?(args)
25
+ rule_based_segment = @rule_based_segments_repository.get_rule_based_segment(@segment_name)
26
+ return false if rule_based_segment.nil?
27
+
28
+ key = update_key(args)
29
+ return false if rule_based_segment[:excluded][:keys].include?(key)
30
+
31
+ return false unless check_excluded_segments(rule_based_segment, key, args)
32
+
33
+ matched = false
34
+ rule_based_segment[:conditions].each do |c|
35
+ condition = SplitIoClient::Condition.new(c, @config)
36
+ next if condition.empty?
37
+
38
+ matched = Helpers::EvaluatorHelper.matcher_type(condition, @segments_repository, @rule_based_segments_repository).match?(args)
39
+
40
+ break if matched
41
+ end
42
+
43
+ @logger.debug("[InRuleSegmentMatcher] #{@segment_name} is in rule based segment -> #{matched}")
44
+ matched
45
+ end
46
+
47
+ private
48
+
49
+ def check_excluded_segments(rule_based_segment, key, args)
50
+ rule_based_segment[:excluded][:segments].each do |segment|
51
+ if segment[:type] == SplitIoClient::Engine::Models::SegmentType::STANDARD &&
52
+ @segments_repository.in_segment?(segment[:name], key)
53
+ return false
54
+ end
55
+ return false if segment[:type] == SplitIoClient::Engine::Models::SegmentType::RULE_BASED_SEGMENT && match_rbs(
56
+ @rule_based_segments_repository.get_rule_based_segment(segment[:name]), args
57
+ )
58
+ end
59
+ true
60
+ end
61
+
62
+ def update_key(args)
63
+ if args[:value].nil? || args[:value].empty?
64
+ args[:matching_key]
65
+ else
66
+ args[:value]
67
+ end
68
+ end
69
+
70
+ def match_rbs(rule_based_segment, args)
71
+ rbs_matcher = RuleBasedSegmentMatcher.new(@segments_repository, @rule_based_segments_repository,
72
+ rule_based_segment[:name], @config)
73
+ rbs_matcher.match?(matching_key: args[:matching_key],
74
+ bucketing_key: args[:value],
75
+ attributes: args[:attributes])
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,9 @@
1
+ module SplitIoClient::Engine::Models
2
+ class EvaluationOptions
3
+ attr_accessor :properties
4
+
5
+ def initialize(properties)
6
+ @properties = properties
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: false
2
+
3
+ module SplitIoClient
4
+ module Engine::Models
5
+ class EventActiveSubscriptions
6
+ attr_accessor :triggered, :handler
7
+
8
+ def initialize(triggered, handler)
9
+ @triggered = triggered
10
+ @handler = handler
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module SplitIoClient::Engine::Models
2
+ class EventsMetadata
3
+ attr_accessor :type, :names
4
+
5
+ def initialize(type, names=nil)
6
+ @type = type
7
+ @names = names
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module SplitIoClient::Engine::Models
2
+ class FallbackTreatment
3
+ attr_accessor :treatment, :config, :label
4
+
5
+ def initialize(treatment, config=nil, label=nil)
6
+ @treatment = treatment
7
+ @config = config
8
+ @label = label
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ module SplitIoClient::Engine::Models
2
+ class FallbackTreatmentsConfiguration
3
+ attr_accessor :global_fallback_treatment, :by_flag_fallback_treatment
4
+
5
+ def initialize(global_fallback_treatment=nil, by_flag_fallback_treatment=nil)
6
+ @global_fallback_treatment = build_global_fallback_treatment(global_fallback_treatment)
7
+ @by_flag_fallback_treatment = build_by_flag_fallback_treatment(by_flag_fallback_treatment)
8
+ end
9
+
10
+ private
11
+
12
+ def build_global_fallback_treatment(global_fallback_treatment)
13
+ if global_fallback_treatment.is_a? String
14
+ return FallbackTreatment.new(global_fallback_treatment)
15
+ end
16
+
17
+ global_fallback_treatment
18
+ end
19
+
20
+ def build_by_flag_fallback_treatment(by_flag_fallback_treatment)
21
+ return nil unless by_flag_fallback_treatment.is_a?(Hash)
22
+ processed_by_flag_fallback_treatment = Hash.new
23
+
24
+ by_flag_fallback_treatment.each do |key, value|
25
+ if value.is_a? String
26
+ processed_by_flag_fallback_treatment[key] = FallbackTreatment.new(value)
27
+ next
28
+ end
29
+
30
+ processed_by_flag_fallback_treatment[key] = value
31
+ end
32
+
33
+ processed_by_flag_fallback_treatment
34
+ end
35
+ end
36
+ end
@@ -6,4 +6,5 @@ class SplitIoClient::Engine::Models::Label
6
6
  NOT_IN_SPLIT = 'not in split'.freeze
7
7
  NOT_READY = 'not ready'.freeze
8
8
  NOT_FOUND = 'definition not found'.freeze
9
+ PREREQUISITES_NOT_MET = 'prerequisites not met'.freeze
9
10
  end
@@ -0,0 +1,4 @@
1
+ class SplitIoClient::Engine::Models::SdkEvent
2
+ SDK_READY = 'SDK_READY'
3
+ SDK_UPDATE = 'SDK_UPDATE'
4
+ end
@@ -0,0 +1,4 @@
1
+ class SplitIoClient::Engine::Models::SdkEventType
2
+ FLAG_UPDATE = 'FLAG_UPDATE'
3
+ SEGMENTS_UPDATE = 'SEGMENTS_UPDATE'
4
+ end
@@ -0,0 +1,8 @@
1
+ class SplitIoClient::Engine::Models::SdkInternalEvent
2
+ SDK_READY = 'SDK_READY'
3
+ FLAGS_UPDATED = 'FLAGS_UPDATED'
4
+ FLAG_KILLED_NOTIFICATION = 'FLAG_KILLED_NOTIFICATION'
5
+ SEGMENTS_UPDATED = 'SEGMENTS_UPDATED'
6
+ RB_SEGMENTS_UPDATED = 'RB_SEGMENTS_UPDATED'
7
+ LARGE_SEGMENTS_UPDATED = 'LARGE_SEGMENTS_UPDATED'
8
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: false
2
+
3
+ module SplitIoClient
4
+ module Engine::Models
5
+ class SdkInternalEventNotification
6
+ attr_reader :internal_event, :metadata
7
+
8
+ def initialize(internal_event, metadata)
9
+ @internal_event = internal_event
10
+ @metadata = metadata
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ class SplitIoClient::Engine::Models::SegmentType
2
+ STANDARD = 'standard'
3
+ RULE_BASED_SEGMENT = 'rule-based'
4
+ end
@@ -0,0 +1,19 @@
1
+ module SplitIoClient
2
+ module Engine
3
+ module Models
4
+ class SplitHttpResponse
5
+ attr_accessor :status, :body
6
+
7
+ def initialize(status, body, success)
8
+ @status = status
9
+ @body = body
10
+ @success = success
11
+ end
12
+
13
+ def success?
14
+ @success
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: false
2
+
3
+ module SplitIoClient
4
+ module Engine::Models
5
+ class ValidSdkEvent
6
+ attr_reader :sdk_event, :valid
7
+
8
+ def initialize(sdk_event, valid)
9
+ @sdk_event = sdk_event
10
+ @valid = valid
11
+ end
12
+ end
13
+ end
14
+ end
@@ -230,6 +230,13 @@ module SplitIoClient
230
230
  )
231
231
  end
232
232
 
233
+ def matcher_in_rule_based_segment(params)
234
+ matcher = params[:matcher]
235
+ segment_name = matcher[:userDefinedSegmentMatcherData] && matcher[:userDefinedSegmentMatcherData][:segmentName]
236
+
237
+ RuleBasedSegmentMatcher.new(params[:segments_repository], params[:rule_based_segments_repository], segment_name, @config)
238
+ end
239
+
233
240
  #
234
241
  # @return [object] the negate value for this condition
235
242
  def negate
@@ -246,6 +253,8 @@ module SplitIoClient
246
253
  # @return [void]
247
254
  def set_partitions
248
255
  partitions_list = []
256
+ return partitions_list unless @data.key?(:partitions) or @data.key?('partitions')
257
+
249
258
  @data[:partitions].each do |p|
250
259
  partition = SplitIoClient::Partition.new(p)
251
260
  partitions_list << partition
@@ -2,9 +2,10 @@ module SplitIoClient
2
2
  module Engine
3
3
  module Parser
4
4
  class Evaluator
5
- def initialize(segments_repository, splits_repository, config)
5
+ def initialize(segments_repository, splits_repository, rb_segment_repository, config)
6
6
  @splits_repository = splits_repository
7
7
  @segments_repository = segments_repository
8
+ @rb_segment_repository = rb_segment_repository
8
9
  @config = config
9
10
  end
10
11
 
@@ -37,6 +38,9 @@ module SplitIoClient
37
38
  end
38
39
 
39
40
  def match(split, keys, attributes)
41
+
42
+ return treatment_hash(Models::Label::PREREQUISITES_NOT_MET, split[:defaultTreatment], split[:changeNumber], split_configurations(split[:defaultTreatment], split)) unless check_prerequisites_matcher(split, keys, attributes)
43
+
40
44
  in_rollout = false
41
45
  key = keys[:bucketing_key] ? keys[:bucketing_key] : keys[:matching_key]
42
46
  legacy_algo = (split[:algo] == 1 || split[:algo] == nil) ? true : false
@@ -58,8 +62,7 @@ module SplitIoClient
58
62
 
59
63
  in_rollout = true
60
64
  end
61
-
62
- condition_matched = matcher_type(condition).match?(
65
+ condition_matched = Helpers::EvaluatorHelper::matcher_type(condition, @segments_repository, @rb_segment_repository).match?(
63
66
  matching_key: keys[:matching_key],
64
67
  bucketing_key: keys[:bucketing_key],
65
68
  evaluator: self,
@@ -70,35 +73,19 @@ module SplitIoClient
70
73
 
71
74
  result = splitter.get_treatment(key, split[:seed], condition.partitions, split[:algo])
72
75
 
73
- if result.nil?
74
- return treatment_hash(Models::Label::NO_RULE_MATCHED, split[:defaultTreatment], split[:changeNumber], split_configurations(split[:defaultTreatment], split))
75
- else
76
- return treatment_hash(c[:label], result, split[:changeNumber],split_configurations(result, split))
77
- end
76
+ return treatment_from_result(result, split, c)
78
77
  end
79
78
 
80
79
  treatment_hash(Models::Label::NO_RULE_MATCHED, split[:defaultTreatment], split[:changeNumber], split_configurations(split[:defaultTreatment], split))
81
80
  end
82
81
 
83
- def matcher_type(condition)
84
- matchers = []
85
-
86
- @segments_repository.adapter.pipelined do
87
- condition.matchers.each do |matcher|
88
- matchers << if matcher[:negate]
89
- condition.negation_matcher(matcher_instance(matcher[:matcherType], condition, matcher))
90
- else
91
- matcher_instance(matcher[:matcherType], condition, matcher)
92
- end
93
- end
94
- end
95
-
96
- final_matcher = condition.create_condition_matcher(matchers)
82
+ private
97
83
 
98
- if final_matcher.nil?
99
- @logger.error('Invalid matcher type')
84
+ def treatment_from_result(result, split, condition)
85
+ if result.nil?
86
+ return treatment_hash(Models::Label::NO_RULE_MATCHED, split[:defaultTreatment], split[:changeNumber], split_configurations(split[:defaultTreatment], split))
100
87
  else
101
- final_matcher
88
+ return treatment_hash(condition[:label], result, split[:changeNumber],split_configurations(result, split))
102
89
  end
103
90
  end
104
91
 
@@ -106,11 +93,18 @@ module SplitIoClient
106
93
  { label: label, treatment: treatment, change_number: change_number, config: configurations }
107
94
  end
108
95
 
109
- def matcher_instance(type, condition, matcher)
110
- condition.send(
111
- "matcher_#{type.downcase}",
112
- matcher: matcher, segments_repository: @segments_repository
113
- )
96
+ def check_prerequisites_matcher(split, keys, attributes)
97
+ if split.key?(:prerequisites) && !split[:prerequisites].nil?
98
+ prerequisites_matcher = SplitIoClient::PrerequisitesMatcher.new(split[:prerequisites], @config.split_logger)
99
+ return prerequisites_matcher.match?(
100
+ matching_key: keys[:matching_key],
101
+ bucketing_key: keys[:bucketing_key],
102
+ evaluator: self,
103
+ attributes: attributes
104
+ )
105
+ end
106
+
107
+ true
114
108
  end
115
109
  end
116
110
  end
@@ -3,9 +3,10 @@
3
3
  module SplitIoClient
4
4
  module Engine
5
5
  class StatusManager
6
- def initialize(config)
6
+ def initialize(config, internal_events_queue)
7
7
  @config = config
8
8
  @sdk_ready = Concurrent::CountDownLatch.new(1)
9
+ @internal_events_queue = internal_events_queue
9
10
  end
10
11
 
11
12
  def ready?
@@ -19,6 +20,11 @@ module SplitIoClient
19
20
 
20
21
  @sdk_ready.count_down
21
22
  @config.logger.info('SplitIO SDK is ready')
23
+ @internal_events_queue.push(
24
+ SplitIoClient::Engine::Models::SdkInternalEventNotification.new(
25
+ SplitIoClient::Engine::Models::SdkInternalEvent::SDK_READY, nil
26
+ )
27
+ )
22
28
  end
23
29
 
24
30
  def wait_until_ready(seconds = nil)
@@ -47,13 +47,13 @@ module SplitIoClient
47
47
  connected = false
48
48
 
49
49
  if @config.streaming_enabled
50
- @config.logger.debug('Starting Streaming mode ...')
50
+ @config.logger.debug('Starting Streaming mode ...') if @config.debug_enabled
51
51
  start_push_status_monitor
52
52
  connected = @push_manager.start_sse
53
53
  end
54
54
 
55
55
  unless connected
56
- @config.logger.debug('Starting Polling mode ...')
56
+ @config.logger.debug('Starting Polling mode ...') if @config.debug_enabled
57
57
  @synchronizer.start_periodic_fetch
58
58
  record_telemetry(Telemetry::Domain::Constants::SYNC_MODE, SYNC_MODE_POLLING)
59
59
  end
@@ -92,7 +92,7 @@ module SplitIoClient
92
92
 
93
93
  def process_connected
94
94
  if @sse_connected.value
95
- @config.logger.debug('Streaming already connected.')
95
+ @config.logger.debug('Streaming already connected.') if @config.debug_enabled
96
96
  return
97
97
  end
98
98
 
@@ -107,7 +107,7 @@ module SplitIoClient
107
107
 
108
108
  def process_forced_stop
109
109
  unless @sse_connected.value
110
- @config.logger.debug('Streaming already disconnected.')
110
+ @config.logger.debug('Streaming already disconnected.') if @config.debug_enabled
111
111
  return
112
112
  end
113
113
 
@@ -120,7 +120,7 @@ module SplitIoClient
120
120
 
121
121
  def process_disconnect(reconnect)
122
122
  unless @sse_connected.value
123
- @config.logger.debug('Streaming already disconnected.')
123
+ @config.logger.debug('Streaming already disconnected.') if @config.debug_enabled
124
124
  return
125
125
  end
126
126
 
@@ -169,7 +169,7 @@ module SplitIoClient
169
169
  when Constants::PUSH_SUBSYSTEM_OFF
170
170
  process_push_shutdown
171
171
  else
172
- @config.logger.debug('Incorrect push status type.')
172
+ @config.logger.debug('Incorrect push status type.') if @config.debug_enabled
173
173
  end
174
174
  end
175
175
  rescue StandardError => e