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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +9 -2
- data/CHANGES.txt +24 -0
- data/LICENSE +169 -13
- data/NOTICE.txt +5 -0
- data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +9 -7
- data/lib/splitclient-rb/cache/filter/bloom_filter.rb +10 -6
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +1 -0
- data/lib/splitclient-rb/cache/repositories/rule_based_segments_repository.rb +136 -0
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +21 -2
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +42 -12
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +24 -10
- data/lib/splitclient-rb/cache/stores/localhost_split_builder.rb +2 -1
- data/lib/splitclient-rb/clients/split_client.rb +146 -62
- data/lib/splitclient-rb/engine/api/client.rb +8 -0
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +1 -0
- data/lib/splitclient-rb/engine/api/splits.rb +100 -24
- data/lib/splitclient-rb/engine/auth_api_client.rb +3 -3
- data/lib/splitclient-rb/engine/common/impressions_manager.rb +56 -30
- data/lib/splitclient-rb/engine/events/events_delivery.rb +20 -0
- data/lib/splitclient-rb/engine/events/events_manager.rb +194 -0
- data/lib/splitclient-rb/engine/events/events_manager_config.rb +96 -0
- data/lib/splitclient-rb/engine/events/events_task.rb +50 -0
- data/lib/splitclient-rb/engine/events/noop_events_queue.rb +13 -0
- data/lib/splitclient-rb/engine/fallback_treatment_calculator.rb +48 -0
- data/lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb +58 -11
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +3 -1
- data/lib/splitclient-rb/engine/matchers/prerequisites_matcher.rb +31 -0
- data/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +78 -0
- data/lib/splitclient-rb/engine/models/evaluation_options.rb +9 -0
- data/lib/splitclient-rb/engine/models/event_active_subscriptions.rb +14 -0
- data/lib/splitclient-rb/engine/models/events_metadata.rb +10 -0
- data/lib/splitclient-rb/engine/models/fallback_treatment.rb +11 -0
- data/lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb +36 -0
- data/lib/splitclient-rb/engine/models/label.rb +1 -0
- data/lib/splitclient-rb/engine/models/sdk_event.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_event_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event.rb +8 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb +14 -0
- data/lib/splitclient-rb/engine/models/segment_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/split_http_response.rb +19 -0
- data/lib/splitclient-rb/engine/models/valid_sdk_event.rb +14 -0
- data/lib/splitclient-rb/engine/parser/condition.rb +9 -0
- data/lib/splitclient-rb/engine/parser/evaluator.rb +24 -30
- data/lib/splitclient-rb/engine/status_manager.rb +7 -1
- data/lib/splitclient-rb/engine/sync_manager.rb +6 -6
- data/lib/splitclient-rb/engine/synchronizer.rb +37 -17
- data/lib/splitclient-rb/helpers/evaluator_helper.rb +37 -0
- data/lib/splitclient-rb/helpers/repository_helper.rb +39 -1
- data/lib/splitclient-rb/helpers/util.rb +12 -3
- data/lib/splitclient-rb/managers/split_manager.rb +2 -1
- data/lib/splitclient-rb/spec.rb +1 -1
- data/lib/splitclient-rb/split_config.rb +45 -5
- data/lib/splitclient-rb/split_factory.rb +27 -21
- data/lib/splitclient-rb/sse/event_source/client.rb +86 -29
- data/lib/splitclient-rb/sse/event_source/event_parser.rb +2 -2
- data/lib/splitclient-rb/sse/event_source/event_types.rb +1 -0
- data/lib/splitclient-rb/sse/notification_manager_keeper.rb +3 -3
- data/lib/splitclient-rb/sse/notification_processor.rb +3 -1
- data/lib/splitclient-rb/sse/workers/segments_worker.rb +4 -4
- data/lib/splitclient-rb/sse/workers/splits_worker.rb +63 -24
- data/lib/splitclient-rb/utilitites.rb +6 -10
- data/lib/splitclient-rb/validators.rb +56 -25
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +22 -0
- data/sonar-project.properties +1 -0
- data/splitclient-rb.gemspec +3 -4
- 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
|
|
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
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
7
|
-
|
|
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
|
|
data/lib/splitclient-rb/spec.rb
CHANGED
|
@@ -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
|
-
|
|
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
|