splitclient-rb 8.8.0 → 8.9.0.pre.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2929d92bdc4d732f21bb8e104316555b0ca458c2eb21df7ecb957d6b1412d65
4
- data.tar.gz: 2be266d8b0948a68faa96c01b24e964308616a32927e27dfb64e1a37f6afbff6
3
+ metadata.gz: e4b77297a7d366bf770ee722755053a57b7335dc0c430976d9c9979df36aa314
4
+ data.tar.gz: 22e38080ffb04c1223637db2d5a38e4fa0f6a7601aeee289bcb66efc661eeb7c
5
5
  SHA512:
6
- metadata.gz: b35604f7de21d0a4a164f07ff42c7930c932977be704cef2d924d87561453a137f0a320fc48e4501f4eb8576fe4f11250062fd8383d5886d7368df6d1d570f36
7
- data.tar.gz: 234c3dd2fd93e34f6348d51177676e950a38e0f628924294c1a72d31cb48e5ae80381a322d15cd7e8d651119c556dbc9b8e965c861ee386b79ff1c3d984c7d39
6
+ metadata.gz: 89f39548cab9c8d6f1e234a696653940ba928bb2c2f061f26a37a471f964f29895d6530bf480d45eab757bf771aea4436bd7b177eb10dbbbd1cfe10dedb5ebc4
7
+ data.tar.gz: 5222a70eaf6a336543dc3447bca2a2ba2d69ddcf8ef686e68451f645ce721c0b1028c0f8e8416d8bc85c2afe37cbc6a2c4ba8be2c0af39a0c9122398c016a5c6
@@ -18,7 +18,7 @@ module SplitIoClient
18
18
  # @param sdk_key [String] the SDK key for your split account
19
19
  #
20
20
  # @return [SplitIoClient] split.io client instance
21
- def initialize(sdk_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer, evaluator, split_validator)
21
+ def initialize(sdk_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer, evaluator, split_validator, fallback_treatment_calculator)
22
22
  @api_key = sdk_key
23
23
  @splits_repository = repositories[:splits]
24
24
  @segments_repository = repositories[:segments]
@@ -32,6 +32,7 @@ module SplitIoClient
32
32
  @telemetry_evaluation_producer = telemetry_evaluation_producer
33
33
  @split_validator = split_validator
34
34
  @evaluator = evaluator
35
+ @fallback_treatment_calculator = fallback_treatment_calculator
35
36
  end
36
37
 
37
38
  def get_treatment(
@@ -50,7 +51,9 @@ module SplitIoClient
50
51
  multiple = false, evaluator = nil
51
52
  )
52
53
  log_deprecated_warning(GET_TREATMENT, evaluator, 'evaluator')
53
- treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT_WITH_CONFIG, multiple, evaluation_options)
54
+ result = treatment(key, split_name, attributes, split_data, store_impressions, GET_TREATMENT_WITH_CONFIG, multiple, evaluation_options)
55
+
56
+ { :config => result[:config], :treatment => result[:treatment] }
54
57
  end
55
58
 
56
59
  def get_treatments(key, split_names, attributes = {}, evaluation_options = nil)
@@ -63,7 +66,11 @@ module SplitIoClient
63
66
  end
64
67
 
65
68
  def get_treatments_with_config(key, split_names, attributes = {}, evaluation_options = nil)
66
- treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG)
69
+ results = treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG)
70
+
71
+ results.map{|key, value|
72
+ [key, { treatment: value[:treatment], config: value[:config] }]
73
+ }.to_h
67
74
  end
68
75
 
69
76
  def get_treatments_by_flag_set(key, flag_set, attributes = {}, evaluation_options = nil)
@@ -89,13 +96,21 @@ module SplitIoClient
89
96
  def get_treatments_with_config_by_flag_set(key, flag_set, attributes = {}, evaluation_options = nil)
90
97
  valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, [flag_set])
91
98
  split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
92
- treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET)
99
+ results = treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET)
100
+
101
+ results.map{|key, value|
102
+ [key, { treatment: value[:treatment], config: value[:config] }]
103
+ }.to_h
93
104
  end
94
105
 
95
106
  def get_treatments_with_config_by_flag_sets(key, flag_sets, attributes = {}, evaluation_options = nil)
96
107
  valid_flag_set = @split_validator.valid_flag_sets(GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, flag_sets)
97
108
  split_names = @splits_repository.get_feature_flags_by_sets(valid_flag_set)
98
- treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS)
109
+ results = treatments(key, split_names, attributes, evaluation_options, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS)
110
+
111
+ results.map{|key, value|
112
+ [key, { treatment: value[:treatment], config: value[:config] }]
113
+ }.to_h
99
114
  end
100
115
 
101
116
  def destroy
@@ -277,7 +292,7 @@ module SplitIoClient
277
292
  if !@config.split_validator.valid_get_treatments_parameters(calling_method, key, sanitized_feature_flag_names, matching_key, bucketing_key, attributes)
278
293
  to_return = Hash.new
279
294
  sanitized_feature_flag_names.each {|name|
280
- to_return[name.to_sym] = control_treatment_with_config
295
+ to_return[name.to_sym] = check_fallback_treatment(name, '')
281
296
  }
282
297
  return to_return
283
298
  end
@@ -286,9 +301,11 @@ module SplitIoClient
286
301
  impressions = []
287
302
  to_return = Hash.new
288
303
  sanitized_feature_flag_names.each {|name|
289
- to_return[name.to_sym] = control_treatment_with_config
304
+ treatment_data = check_fallback_treatment(name, Engine::Models::Label::NOT_READY)
305
+ to_return[name.to_sym] = treatment_data
306
+
290
307
  impressions << { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, name.to_sym,
291
- control_treatment_with_config.merge({ :label => Engine::Models::Label::NOT_READY }), false, { attributes: attributes, time: nil },
308
+ get_treatment_without_config(treatment_data), false, { attributes: attributes, time: nil },
292
309
  evaluation_options), :disabled => false }
293
310
  }
294
311
  @impressions_manager.track(impressions)
@@ -308,7 +325,7 @@ module SplitIoClient
308
325
  if feature_flag.nil?
309
326
  @config.logger.warn("#{calling_method}: you passed #{key} that " \
310
327
  'does not exist in this environment, please double check what feature flags exist in the Split user interface')
311
- invalid_treatments[key] = control_treatment_with_config
328
+ invalid_treatments[key] = check_fallback_treatment(key, Engine::Models::Label::NOT_FOUND)
312
329
  next
313
330
  end
314
331
  treatments_labels_change_numbers, impressions = evaluate_treatment(feature_flag, key, bucketing_key, matching_key, attributes, calling_method, false, evaluation_options)
@@ -344,7 +361,7 @@ module SplitIoClient
344
361
 
345
362
  attributes = parsed_attributes(attributes)
346
363
 
347
- return parsed_treatment(control_treatment, multiple) unless valid_client && @config.split_validator.valid_get_treatment_parameters(calling_method, key, feature_flag_name, matching_key, bucketing_key, attributes)
364
+ return parsed_treatment(check_fallback_treatment(feature_flag_name, ""), multiple) unless valid_client && @config.split_validator.valid_get_treatment_parameters(calling_method, key, feature_flag_name, matching_key, bucketing_key, attributes)
348
365
 
349
366
  bucketing_key = bucketing_key ? bucketing_key.to_s : nil
350
367
  matching_key = matching_key.to_s
@@ -373,7 +390,7 @@ module SplitIoClient
373
390
  if feature_flag.nil? && ready?
374
391
  @config.logger.warn("#{calling_method}: you passed #{feature_flag_name} that " \
375
392
  'does not exist in this environment, please double check what feature flags exist in the Split user interface')
376
- return parsed_treatment(control_treatment.merge({ :label => Engine::Models::Label::NOT_FOUND }), multiple), nil
393
+ return check_fallback_treatment(feature_flag_name, Engine::Models::Label::NOT_FOUND), nil
377
394
  end
378
395
 
379
396
  if !feature_flag.nil? && ready?
@@ -383,7 +400,7 @@ module SplitIoClient
383
400
  impressions_disabled = feature_flag[:impressionsDisabled]
384
401
  else
385
402
  @config.logger.error("#{calling_method}: the SDK is not ready, results may be incorrect for feature flag #{feature_flag_name}. Make sure to wait for SDK readiness before using this method.")
386
- treatment_data = control_treatment.merge({ :label => Engine::Models::Label::NOT_READY })
403
+ treatment_data = check_fallback_treatment(feature_flag_name, Engine::Models::Label::NOT_READY)
387
404
  impressions_disabled = false
388
405
  end
389
406
 
@@ -396,22 +413,16 @@ module SplitIoClient
396
413
  rescue StandardError => e
397
414
  @config.log_found_exception(__method__.to_s, e)
398
415
  record_exception(calling_method)
399
- impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, control_treatment, false, { attributes: attributes, time: nil }, evaluation_options), :disabled => false }
416
+ treatment_data = check_fallback_treatment(feature_flag_name, Engine::Models::Label::EXCEPTION)
417
+ impression_decorator = { :impression => @impressions_manager.build_impression(matching_key, bucketing_key, feature_flag_name, get_treatment_without_config(treatment_data), false, { attributes: attributes, time: nil }, evaluation_options), :disabled => false }
418
+
400
419
  impressions_decorator << impression_decorator unless impression_decorator.nil?
401
420
 
402
- return parsed_treatment(control_treatment.merge({ :label => Engine::Models::Label::EXCEPTION }), multiple), impressions_decorator
421
+ return parsed_treatment(treatment_data, multiple), impressions_decorator
403
422
  end
404
423
  return parsed_treatment(treatment_data, multiple), impressions_decorator
405
424
  end
406
425
 
407
- def control_treatment
408
- { :treatment => Engine::Models::Treatment::CONTROL }
409
- end
410
-
411
- def control_treatment_with_config
412
- {:treatment => Engine::Models::Treatment::CONTROL, :config => nil}
413
- end
414
-
415
426
  def variable_size(value)
416
427
  value.is_a?(String) ? value.length : 0
417
428
  end
@@ -472,5 +483,39 @@ module SplitIoClient
472
483
  @telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TRACK)
473
484
  end
474
485
  end
486
+
487
+ def check_fallback_treatment(feature_name, label)
488
+ return {
489
+ label: (label != '')? label : nil,
490
+ treatment: Engine::Models::Treatment::CONTROL,
491
+ config: nil,
492
+ change_number: nil
493
+ } unless feature_name.is_a?(Symbol) || feature_name.is_a?(String)
494
+
495
+ fallback_treatment = @fallback_treatment_calculator.resolve(feature_name.to_sym, label)
496
+
497
+ {
498
+ label: (label != '')? fallback_treatment.label : nil,
499
+ treatment: fallback_treatment.treatment,
500
+ config: get_fallback_config(fallback_treatment),
501
+ change_number: nil
502
+ }
503
+ end
504
+
505
+ def get_treatment_without_config(treatment)
506
+ {
507
+ label: treatment[:label],
508
+ treatment: treatment[:treatment],
509
+ }
510
+ end
511
+
512
+ def get_fallback_config(fallback_treatment)
513
+ if fallback_treatment.config != nil
514
+ return fallback_treatment.config
515
+ end
516
+
517
+ return nil
518
+ end
519
+
475
520
  end
476
521
  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
@@ -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
@@ -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
 
@@ -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
 
@@ -697,5 +701,37 @@ module SplitIoClient
697
701
 
698
702
  return ''.freeze
699
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
700
736
  end
701
737
  end
@@ -58,8 +58,8 @@ module SplitIoClient
58
58
  @evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @rule_based_segment_repository, @config)
59
59
 
60
60
  start!
61
-
62
- @client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator)
61
+ fallback_treatment_calculator = SplitIoClient::Engine::FallbackTreatmentCalculator.new(@config.fallback_treatments_configuration)
62
+ @client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator, fallback_treatment_calculator)
63
63
  @manager = SplitManager.new(@splits_repository, @status_manager, @config)
64
64
  end
65
65
 
@@ -4,6 +4,8 @@ module SplitIoClient
4
4
  class Validators
5
5
 
6
6
  Flagset_regex = /^[a-z0-9][_a-z0-9]{0,49}$/
7
+ Fallback_treatment_regex = /^[0-9]+[.a-zA-Z0-9_-]*$|^[a-zA-Z]+[a-zA-Z0-9_-]*$/
8
+ Fallback_treatment_size = 100
7
9
 
8
10
  def initialize(config)
9
11
  @config = config
@@ -68,7 +70,7 @@ module SplitIoClient
68
70
  log_invalid_flag_set_type(method)
69
71
  elsif flag_set.is_a?(String) && flag_set.empty?
70
72
  log_invalid_flag_set_type(method)
71
- elsif !flag_set.empty? && string_match?(flag_set.strip.downcase, method)
73
+ elsif !flag_set.empty? && string_match?(flag_set.strip.downcase, method, Flagset_regex, :log_invalid_match)
72
74
  valid_flag_sets.add(flag_set.strip.downcase)
73
75
  else
74
76
  log_invalid_flag_set_type(method)
@@ -77,6 +79,46 @@ module SplitIoClient
77
79
  !valid_flag_sets.empty? ? valid_flag_sets.to_a.sort : []
78
80
  end
79
81
 
82
+ def validate_fallback_treatment(method, fallback_treatment)
83
+ if !fallback_treatment.is_a? Engine::Models::FallbackTreatment
84
+ @config.logger.warn("#{method}: Fallback treatment instance should be FallbackTreatment, input is discarded")
85
+ return false
86
+ end
87
+
88
+ if !fallback_treatment.treatment.is_a? String
89
+ @config.logger.warn("#{method}: Fallback treatment value should be str type, input is discarded")
90
+ return false
91
+ end
92
+
93
+ return false unless string_match?(fallback_treatment.treatment, method, Fallback_treatment_regex, :log_invalid_fallback_treatment)
94
+
95
+ if fallback_treatment.treatment.size > Fallback_treatment_size
96
+ @config.logger.warn("#{method}: Fallback treatment size should not exceed #{Fallback_treatment_size} characters")
97
+ return false
98
+ end
99
+
100
+ true
101
+ end
102
+
103
+ def valid_split_name?(method, split_name)
104
+ if split_name.nil?
105
+ log_nil(:split_name, method)
106
+ return false
107
+ end
108
+
109
+ unless string?(split_name)
110
+ log_invalid_type(:split_name, method)
111
+ return false
112
+ end
113
+
114
+ if empty_string?(split_name)
115
+ log_empty_string(:split_name, method)
116
+ return false
117
+ end
118
+
119
+ true
120
+ end
121
+
80
122
  private
81
123
 
82
124
  def string?(value)
@@ -91,9 +133,9 @@ module SplitIoClient
91
133
  (value.is_a?(Numeric) && !value.to_f.nan?) || string?(value)
92
134
  end
93
135
 
94
- def string_match?(value, method)
95
- if Flagset_regex.match(value) == nil
96
- log_invalid_match(value, method)
136
+ def string_match?(value, method, regex_exp, log_if_invalid)
137
+ if regex_exp.match(value) == nil
138
+ method(log_if_invalid).call(value, method)
97
139
  false
98
140
  else
99
141
  true
@@ -132,25 +174,6 @@ module SplitIoClient
132
174
  @config.logger.error("#{method}: #{key} is too long - must be #{@config.max_key_size} characters or less")
133
175
  end
134
176
 
135
- def valid_split_name?(method, split_name)
136
- if split_name.nil?
137
- log_nil(:split_name, method)
138
- return false
139
- end
140
-
141
- unless string?(split_name)
142
- log_invalid_type(:split_name, method)
143
- return false
144
- end
145
-
146
- if empty_string?(split_name)
147
- log_empty_string(:split_name, method)
148
- return false
149
- end
150
-
151
- true
152
- end
153
-
154
177
  def valid_key?(method, key)
155
178
  if key.nil?
156
179
  log_nil(:key, method)
@@ -326,5 +349,9 @@ module SplitIoClient
326
349
 
327
350
  true
328
351
  end
352
+
353
+ def log_invalid_fallback_treatment(key, method)
354
+ @config.logger.warn("#{method}: Invalid treatment #{key}, Fallback treatment should match regex #{Fallback_treatment_regex}")
355
+ end
329
356
  end
330
357
  end
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '8.8.0'
2
+ VERSION = '8.9.0-rc1'
3
3
  end
@@ -110,8 +110,11 @@ require 'splitclient-rb/engine/models/segment_type'
110
110
  require 'splitclient-rb/engine/models/treatment'
111
111
  require 'splitclient-rb/engine/models/split_http_response'
112
112
  require 'splitclient-rb/engine/models/evaluation_options'
113
+ require 'splitclient-rb/engine/models/fallback_treatment.rb'
114
+ require 'splitclient-rb/engine/models/fallback_treatments_configuration.rb'
113
115
  require 'splitclient-rb/engine/auth_api_client'
114
116
  require 'splitclient-rb/engine/back_off'
117
+ require 'splitclient-rb/engine/fallback_treatment_calculator.rb'
115
118
  require 'splitclient-rb/engine/push_manager'
116
119
  require 'splitclient-rb/engine/status_manager'
117
120
  require 'splitclient-rb/engine/sync_manager'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: splitclient-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.8.0
4
+ version: 8.9.0.pre.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Split Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-26 00:00:00.000000000 Z
11
+ date: 2025-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allocation_stats
@@ -481,6 +481,7 @@ files:
481
481
  - lib/splitclient-rb/engine/common/impressions_manager.rb
482
482
  - lib/splitclient-rb/engine/common/noop_impressions_counter.rb
483
483
  - lib/splitclient-rb/engine/evaluator/splitter.rb
484
+ - lib/splitclient-rb/engine/fallback_treatment_calculator.rb
484
485
  - lib/splitclient-rb/engine/impressions/noop_unique_keys_tracker.rb
485
486
  - lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb
486
487
  - lib/splitclient-rb/engine/matchers/all_keys_matcher.rb
@@ -515,6 +516,8 @@ files:
515
516
  - lib/splitclient-rb/engine/matchers/whitelist_matcher.rb
516
517
  - lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb
517
518
  - lib/splitclient-rb/engine/models/evaluation_options.rb
519
+ - lib/splitclient-rb/engine/models/fallback_treatment.rb
520
+ - lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb
518
521
  - lib/splitclient-rb/engine/models/label.rb
519
522
  - lib/splitclient-rb/engine/models/segment_type.rb
520
523
  - lib/splitclient-rb/engine/models/split.rb
@@ -592,9 +595,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
592
595
  version: 2.5.0
593
596
  required_rubygems_version: !ruby/object:Gem::Requirement
594
597
  requirements:
595
- - - ">="
598
+ - - ">"
596
599
  - !ruby/object:Gem::Version
597
- version: '0'
600
+ version: 1.3.1
598
601
  requirements: []
599
602
  rubyforge_project:
600
603
  rubygems_version: 2.7.6.2