splitclient-rb 6.4.1 → 7.0.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/CHANGES.txt +10 -1
  3. data/Detailed-README.md +9 -21
  4. data/lib/splitclient-rb/cache/adapters/cache_adapter.rb +3 -3
  5. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +5 -4
  6. data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +4 -3
  7. data/lib/splitclient-rb/cache/repositories/events_repository.rb +10 -9
  8. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +7 -6
  9. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +5 -4
  10. data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +9 -8
  11. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +3 -2
  12. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +5 -4
  13. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +6 -4
  14. data/lib/splitclient-rb/cache/repositories/repository.rb +7 -2
  15. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +6 -5
  16. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +56 -14
  17. data/lib/splitclient-rb/cache/routers/impression_router.rb +5 -4
  18. data/lib/splitclient-rb/cache/senders/events_sender.rb +7 -6
  19. data/lib/splitclient-rb/cache/senders/impressions_sender.rb +10 -9
  20. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +9 -8
  21. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +19 -10
  22. data/lib/splitclient-rb/cache/stores/segment_store.rb +15 -28
  23. data/lib/splitclient-rb/cache/stores/split_store.rb +13 -15
  24. data/lib/splitclient-rb/clients/localhost_split_client.rb +8 -7
  25. data/lib/splitclient-rb/clients/split_client.rb +65 -35
  26. data/lib/splitclient-rb/engine/api/client.rb +17 -13
  27. data/lib/splitclient-rb/engine/api/events.rb +7 -6
  28. data/lib/splitclient-rb/engine/api/impressions.rb +6 -5
  29. data/lib/splitclient-rb/engine/api/metrics.rb +8 -7
  30. data/lib/splitclient-rb/engine/api/segments.rb +11 -10
  31. data/lib/splitclient-rb/engine/api/splits.rb +6 -5
  32. data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +1 -1
  33. data/lib/splitclient-rb/engine/matchers/between_matcher.rb +7 -5
  34. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +5 -4
  35. data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +4 -4
  36. data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +3 -3
  37. data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +7 -5
  38. data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +3 -2
  39. data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +5 -4
  40. data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +3 -2
  41. data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +6 -4
  42. data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +3 -3
  43. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +6 -4
  44. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +6 -4
  45. data/lib/splitclient-rb/engine/matchers/matcher.rb +4 -0
  46. data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +3 -2
  47. data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +3 -2
  48. data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +4 -4
  49. data/lib/splitclient-rb/engine/matchers/set_matcher.rb +2 -1
  50. data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +4 -3
  51. data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +3 -2
  52. data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +7 -5
  53. data/lib/splitclient-rb/engine/models/label.rb +2 -0
  54. data/lib/splitclient-rb/engine/parser/condition.rb +31 -20
  55. data/lib/splitclient-rb/engine/parser/evaluator.rb +3 -2
  56. data/lib/splitclient-rb/engine/parser/split_adapter.rb +9 -7
  57. data/lib/splitclient-rb/localhost_split_factory.rb +3 -2
  58. data/lib/splitclient-rb/managers/split_manager.rb +39 -5
  59. data/lib/splitclient-rb/redis_metrics_fixer.rb +5 -4
  60. data/lib/splitclient-rb/split_config.rb +35 -14
  61. data/lib/splitclient-rb/split_factory.rb +44 -32
  62. data/lib/splitclient-rb/split_factory_builder.rb +4 -5
  63. data/lib/splitclient-rb/split_factory_registry.rb +51 -0
  64. data/lib/splitclient-rb/split_logger.rb +5 -14
  65. data/lib/splitclient-rb/validators.rb +19 -16
  66. data/lib/splitclient-rb/version.rb +1 -1
  67. data/lib/splitclient-rb.rb +2 -1
  68. metadata +3 -2
@@ -4,14 +4,15 @@ module SplitIoClient
4
4
  module Cache
5
5
  module Senders
6
6
  class ImpressionsSender
7
- def initialize(impressions_repository, api_key)
7
+ def initialize(impressions_repository, api_key, config)
8
8
  @impressions_repository = impressions_repository
9
9
  @api_key = api_key
10
+ @config = config
10
11
  end
11
12
 
12
13
  def call
13
- if SplitIoClient.configuration.disable_impressions
14
- SplitIoClient.configuration.logger.info('Disabling impressions service by config')
14
+ if @config.disable_impressions
15
+ @config.logger.info('Disabling impressions service by config')
15
16
  return
16
17
  end
17
18
 
@@ -31,19 +32,19 @@ module SplitIoClient
31
32
  private
32
33
 
33
34
  def impressions_thread
34
- SplitIoClient.configuration.threads[:impressions_sender] = Thread.new do
35
+ @config.threads[:impressions_sender] = Thread.new do
35
36
  begin
36
- SplitIoClient.configuration.logger.info('Starting impressions service')
37
+ @config.logger.info('Starting impressions service')
37
38
 
38
39
  loop do
39
40
  post_impressions(false)
40
41
 
41
- sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.impressions_refresh_rate))
42
+ sleep(SplitIoClient::Utilities.randomize_interval(@config.impressions_refresh_rate))
42
43
  end
43
44
  rescue SplitIoClient::SDKShutdownException
44
45
  post_impressions
45
46
 
46
- SplitIoClient.configuration.logger.info('Posting impressions due to shutdown')
47
+ @config.logger.info('Posting impressions due to shutdown')
47
48
  end
48
49
  end
49
50
  end
@@ -54,11 +55,11 @@ module SplitIoClient
54
55
 
55
56
  impressions_api.post(formatted_impressions)
56
57
  rescue StandardError => error
57
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
58
+ @config.log_found_exception(__method__.to_s, error)
58
59
  end
59
60
 
60
61
  def impressions_api
61
- @impressions_api ||= SplitIoClient::Api::Impressions.new(@api_key)
62
+ @impressions_api ||= SplitIoClient::Api::Impressions.new(@api_key, @config)
62
63
  end
63
64
  end
64
65
  end
@@ -4,9 +4,10 @@ module SplitIoClient
4
4
  module Cache
5
5
  module Senders
6
6
  class MetricsSender
7
- def initialize(metrics_repository, api_key)
7
+ def initialize(metrics_repository, api_key, config)
8
8
  @metrics_repository = metrics_repository
9
9
  @api_key = api_key
10
+ @config = config
10
11
  end
11
12
 
12
13
  def call
@@ -24,19 +25,19 @@ module SplitIoClient
24
25
  private
25
26
 
26
27
  def metrics_thread
27
- SplitIoClient.configuration.threads[:metrics_sender] = Thread.new do
28
+ @config.threads[:metrics_sender] = Thread.new do
28
29
  begin
29
- SplitIoClient.configuration.logger.info('Starting metrics service')
30
-
30
+ @config.logger.info('Starting metrics service')
31
+
31
32
  loop do
32
33
  post_metrics
33
34
 
34
- sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.metrics_refresh_rate))
35
+ sleep(SplitIoClient::Utilities.randomize_interval(@config.metrics_refresh_rate))
35
36
  end
36
37
  rescue SplitIoClient::SDKShutdownException
37
38
  post_metrics
38
39
 
39
- SplitIoClient.configuration.logger.info('Posting metrics due to shutdown')
40
+ @config.logger.info('Posting metrics due to shutdown')
40
41
  end
41
42
  end
42
43
  end
@@ -44,11 +45,11 @@ module SplitIoClient
44
45
  def post_metrics
45
46
  metrics_api.post
46
47
  rescue StandardError => error
47
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
48
+ @config.log_found_exception(__method__.to_s, error)
48
49
  end
49
50
 
50
51
  def metrics_api
51
- @metrics_api ||= SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository)
52
+ @metrics_api ||= SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository, @config)
52
53
  end
53
54
  end
54
55
  end
@@ -7,37 +7,46 @@ module SplitIoClient
7
7
  class SDKBlocker
8
8
  attr_reader :splits_repository
9
9
 
10
- def initialize(splits_repository, segments_repository)
10
+ def initialize(splits_repository, segments_repository, config)
11
11
  @splits_repository = splits_repository
12
12
  @segments_repository = segments_repository
13
+ @config = config
13
14
 
14
- @splits_repository.not_ready!
15
- @segments_repository.not_ready!
15
+ if @config.standalone?
16
+ @splits_repository.not_ready!
17
+ @segments_repository.not_ready!
18
+ end
16
19
  end
17
20
 
18
21
  def splits_ready!
19
- @splits_repository.ready!
22
+ if !ready?
23
+ @splits_repository.ready!
24
+ @config.logger.info('splits are ready')
25
+ end
20
26
  end
21
27
 
22
28
  def segments_ready!
23
- @segments_repository.ready!
29
+ if !ready?
30
+ @segments_repository.ready!
31
+ @config.logger.info('segments are ready')
32
+ end
24
33
  end
25
34
 
26
- def block
35
+ def block(time = nil)
27
36
  begin
28
- Timeout::timeout(SplitIoClient.configuration.block_until_ready) do
37
+ timeout = time || @config.block_until_ready
38
+ Timeout::timeout(timeout) do
29
39
  sleep 0.1 until ready?
30
40
  end
31
41
  rescue Timeout::Error
32
42
  fail SDKBlockerTimeoutExpiredException, 'SDK start up timeout expired'
33
43
  end
34
44
 
35
- SplitIoClient.configuration.logger.info('SplitIO SDK is ready')
36
- SplitIoClient.configuration.threads[:split_store].run
37
- SplitIoClient.configuration.threads[:segment_store].run
45
+ @config.logger.info('SplitIO SDK is ready')
38
46
  end
39
47
 
40
48
  def ready?
49
+ return true if @config.consumer?
41
50
  @splits_repository.ready? && @segments_repository.ready?
42
51
  end
43
52
  end
@@ -4,10 +4,11 @@ module SplitIoClient
4
4
  class SegmentStore
5
5
  attr_reader :segments_repository
6
6
 
7
- def initialize(segments_repository, api_key, metrics, sdk_blocker = nil)
7
+ def initialize(segments_repository, api_key, metrics, config, sdk_blocker = nil)
8
8
  @segments_repository = segments_repository
9
9
  @api_key = api_key
10
10
  @metrics = metrics
11
+ @config = config
11
12
  @sdk_blocker = sdk_blocker
12
13
  end
13
14
 
@@ -28,42 +29,28 @@ module SplitIoClient
28
29
  private
29
30
 
30
31
  def segments_thread
31
- SplitIoClient.configuration.threads[:segment_store] = Thread.new do
32
- SplitIoClient.configuration.logger.info('Starting segments fetcher service')
33
- SplitIoClient.configuration.block_until_ready > 0 ? blocked_store : unblocked_store
34
- end
35
- end
32
+ @config.threads[:segment_store] = Thread.new do
33
+ @config.logger.info('Starting segments fetcher service')
36
34
 
37
- def blocked_store
38
- loop do
39
- next unless @sdk_blocker.splits_repository.ready?
35
+ loop do
36
+ next unless @sdk_blocker.splits_repository.ready?
40
37
 
41
- store_segments
42
- SplitIoClient.configuration.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if SplitIoClient.configuration.debug_enabled
38
+ store_segments
39
+ @config.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if @config.debug_enabled
43
40
 
44
- unless @sdk_blocker.ready?
45
- @sdk_blocker.segments_ready!
46
- SplitIoClient.configuration.logger.info('segments are ready')
41
+ sleep_for = random_interval(@config.segments_refresh_rate)
42
+ @config.logger.debug("Segments store is sleeping for: #{sleep_for} seconds") if @config.debug_enabled
43
+ sleep(sleep_for)
47
44
  end
48
-
49
- sleep_for = random_interval(SplitIoClient.configuration.segments_refresh_rate)
50
- SplitIoClient.configuration.logger.debug("Segments store is sleeping for: #{sleep_for} seconds") if SplitIoClient.configuration.debug_enabled
51
- sleep(sleep_for)
52
- end
53
- end
54
-
55
- def unblocked_store
56
- loop do
57
- store_segments
58
-
59
- sleep(random_interval(SplitIoClient.configuration.segments_refresh_rate))
60
45
  end
61
46
  end
62
47
 
63
48
  def store_segments
64
49
  segments_api.store_segments_by_names(@segments_repository.used_segment_names)
50
+
51
+ @sdk_blocker.segments_ready!
65
52
  rescue StandardError => error
66
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
53
+ @config.log_found_exception(__method__.to_s, error)
67
54
  end
68
55
 
69
56
  def random_interval(interval)
@@ -73,7 +60,7 @@ module SplitIoClient
73
60
  end
74
61
 
75
62
  def segments_api
76
- @segments_api ||= SplitIoClient::Api::Segments.new(@api_key, @metrics, @segments_repository)
63
+ @segments_api ||= SplitIoClient::Api::Segments.new(@api_key, @metrics, @segments_repository, @config)
77
64
  end
78
65
  end
79
66
  end
@@ -4,10 +4,11 @@ module SplitIoClient
4
4
  class SplitStore
5
5
  attr_reader :splits_repository
6
6
 
7
- def initialize(splits_repository, api_key, metrics, sdk_blocker = nil)
7
+ def initialize(splits_repository, api_key, metrics, config, sdk_blocker = nil)
8
8
  @splits_repository = splits_repository
9
9
  @api_key = api_key
10
10
  @metrics = metrics
11
+ @config = config
11
12
  @sdk_blocker = sdk_blocker
12
13
  end
13
14
 
@@ -28,12 +29,12 @@ module SplitIoClient
28
29
  private
29
30
 
30
31
  def splits_thread
31
- SplitIoClient.configuration.threads[:split_store] = Thread.new do
32
- SplitIoClient.configuration.logger.info('Starting splits fetcher service')
32
+ @config.threads[:split_store] = Thread.new do
33
+ @config.logger.info('Starting splits fetcher service')
33
34
  loop do
34
35
  store_splits
35
36
 
36
- sleep(random_interval(SplitIoClient.configuration.features_refresh_rate))
37
+ sleep(random_interval(@config.features_refresh_rate))
37
38
  end
38
39
  end
39
40
  end
@@ -48,15 +49,12 @@ module SplitIoClient
48
49
  @splits_repository.set_segment_names(data[:segment_names])
49
50
  @splits_repository.set_change_number(data[:till])
50
51
 
51
- SplitIoClient.configuration.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if SplitIoClient.configuration.debug_enabled
52
+ @config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled
52
53
 
53
- if SplitIoClient.configuration.block_until_ready > 0 && !@sdk_blocker.ready?
54
- @sdk_blocker.splits_ready!
55
- SplitIoClient.configuration.logger.info('splits are ready')
56
- end
54
+ @sdk_blocker.splits_ready!
57
55
 
58
56
  rescue StandardError => error
59
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
57
+ @config.log_found_exception(__method__.to_s, error)
60
58
  end
61
59
 
62
60
  def random_interval(interval)
@@ -71,7 +69,7 @@ module SplitIoClient
71
69
 
72
70
  def add_split_unless_archived(split)
73
71
  if Engine::Models::Split.archived?(split)
74
- SplitIoClient.configuration.logger.debug("Seeing archived split #{split[:name]}") if SplitIoClient.configuration.debug_enabled
72
+ @config.logger.debug("Seeing archived split #{split[:name]}") if @config.debug_enabled
75
73
 
76
74
  remove_archived_split(split)
77
75
  else
@@ -80,13 +78,13 @@ module SplitIoClient
80
78
  end
81
79
 
82
80
  def remove_archived_split(split)
83
- SplitIoClient.configuration.logger.debug("removing split from store(#{split})") if SplitIoClient.configuration.debug_enabled
81
+ @config.logger.debug("removing split from store(#{split})") if @config.debug_enabled
84
82
 
85
- @splits_repository.remove_split(split[:name])
83
+ @splits_repository.remove_split(split)
86
84
  end
87
85
 
88
86
  def store_split(split)
89
- SplitIoClient.configuration.logger.debug("storing split (#{split[:name]})") if SplitIoClient.configuration.debug_enabled
87
+ @config.logger.debug("storing split (#{split[:name]})") if @config.debug_enabled
90
88
 
91
89
  @splits_repository.add_split(split)
92
90
  end
@@ -94,7 +92,7 @@ module SplitIoClient
94
92
  private
95
93
 
96
94
  def splits_api
97
- @splits_api ||= SplitIoClient::Api::Splits.new(@api_key, @metrics)
95
+ @splits_api ||= SplitIoClient::Api::Splits.new(@api_key, @metrics, @config)
98
96
  end
99
97
  end
100
98
  end
@@ -13,10 +13,11 @@ module SplitIoClient
13
13
  # @param splits_file [File] file that contains some splits
14
14
  #
15
15
  # @return [LocalhostSplitIoClient] split.io localhost client instance
16
- def initialize(splits_file, reload_rate = nil)
16
+ def initialize(splits_file, config, reload_rate = nil)
17
17
  @localhost_mode = true
18
18
  @localhost_mode_features = []
19
19
  load_localhost_mode_features(splits_file, reload_rate)
20
+ @config = config
20
21
  end
21
22
 
22
23
  #
@@ -101,12 +102,12 @@ module SplitIoClient
101
102
  parsed_control_treatment = parsed_treatment(control_treatment)
102
103
 
103
104
  bucketing_key, matching_key = keys_from_key(key)
104
- return parsed_control_treatment unless SplitIoClient::Validators.valid_get_treatment_parameters(calling_method, key, split_name, matching_key, bucketing_key, attributes)
105
+ return parsed_control_treatment unless @config.split_validator.valid_get_treatment_parameters(calling_method, key, split_name, matching_key, bucketing_key, attributes)
105
106
 
106
107
  sanitized_split_name = split_name.to_s.strip
107
108
 
108
109
  if split_name.to_s != sanitized_split_name
109
- SplitIoClient.configuration.logger.warn("get_treatment: split_name #{split_name} has extra whitespace, trimming")
110
+ @config.logger.warn("get_treatment: split_name #{split_name} has extra whitespace, trimming")
110
111
  split_name = sanitized_split_name
111
112
  end
112
113
 
@@ -127,12 +128,12 @@ module SplitIoClient
127
128
  end
128
129
 
129
130
  def get_localhost_treatments(key, split_names, attributes = nil, calling_method = 'get_treatments')
130
- return nil unless SplitIoClient::Validators.valid_get_treatments_parameters(calling_method, split_names)
131
+ return nil unless @config.split_validator.valid_get_treatments_parameters(calling_method, split_names)
131
132
 
132
133
  sanitized_split_names = sanitize_split_names(calling_method, split_names)
133
134
 
134
135
  if sanitized_split_names.empty?
135
- SplitIoClient.configuration.logger.error("#{calling_method}: split_names must be a non-empty Array")
136
+ @config.logger.error("#{calling_method}: split_names must be a non-empty Array")
136
137
  return {}
137
138
  end
138
139
 
@@ -146,10 +147,10 @@ module SplitIoClient
146
147
  if (split_name.is_a?(String) || split_name.is_a?(Symbol)) && !split_name.empty?
147
148
  true
148
149
  elsif split_name.is_a?(String) && split_name.empty?
149
- SplitIoClient.configuration.logger.warn("#{calling_method}: you passed an empty split_name, split_name must be a non-empty String or a Symbol")
150
+ @config.logger.warn("#{calling_method}: you passed an empty split_name, split_name must be a non-empty String or a Symbol")
150
151
  false
151
152
  else
152
- SplitIoClient.configuration.logger.warn("#{calling_method}: you passed an invalid split_name, split_name must be a non-empty String or a Symbol")
153
+ @config.logger.warn("#{calling_method}: you passed an invalid split_name, split_name must be a non-empty String or a Symbol")
153
154
  false
154
155
  end
155
156
  end
@@ -9,14 +9,16 @@ module SplitIoClient
9
9
  # @param api_key [String] the API key for your split account
10
10
  #
11
11
  # @return [SplitIoClient] split.io client instance
12
- def initialize(api_key, adapter = nil, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository)
12
+ def initialize(api_key, adapter = nil, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository, sdk_blocker, config)
13
+ @api_key = api_key
13
14
  @splits_repository = splits_repository
14
15
  @segments_repository = segments_repository
15
16
  @impressions_repository = impressions_repository
16
17
  @metrics_repository = metrics_repository
17
18
  @events_repository = events_repository
19
+ @sdk_blocker = sdk_blocker
18
20
  @destroyed = false
19
-
21
+ @config = config
20
22
  @adapter = adapter
21
23
  end
22
24
 
@@ -52,27 +54,30 @@ module SplitIoClient
52
54
  end
53
55
 
54
56
  def destroy
55
- SplitIoClient.configuration.logger.info('Split client shutdown started...') if SplitIoClient.configuration.debug_enabled
57
+ @config.logger.info('Split client shutdown started...') if @config.debug_enabled
56
58
 
57
- SplitIoClient.configuration.threads.select { |name, thread| name.to_s.end_with? 'sender' }.values.each do |thread|
59
+ @config.threads.select { |name, thread| name.to_s.end_with? 'sender' }.values.each do |thread|
58
60
  thread.raise(SplitIoClient::SDKShutdownException)
59
61
  thread.join
60
62
  end
61
63
 
62
- SplitIoClient.configuration.threads.values.each { |thread| Thread.kill(thread) }
64
+ @config.threads.values.each { |thread| Thread.kill(thread) }
63
65
 
64
66
  @splits_repository.clear
65
67
  @segments_repository.clear
66
68
 
67
- SplitIoClient.configuration.logger.info('Split client shutdown complete') if SplitIoClient.configuration.debug_enabled
68
- SplitIoClient.configuration.valid_mode = false
69
+ SplitIoClient.load_factory_registry
70
+ SplitIoClient.split_factory_registry.remove(@api_key)
71
+
72
+ @config.logger.info('Split client shutdown complete') if @config.debug_enabled
73
+ @config.valid_mode = false
69
74
  @destroyed = true
70
75
  end
71
76
 
72
77
  def store_impression(split_name, matching_key, bucketing_key, treatment, store_impressions, attributes)
73
78
  time = (Time.now.to_f * 1000.0).to_i
74
79
 
75
- return if SplitIoClient.configuration.disable_impressions || !store_impressions
80
+ return if @config.disable_impressions || !store_impressions
76
81
 
77
82
  @impressions_repository.add(
78
83
  matching_key,
@@ -85,7 +90,7 @@ module SplitIoClient
85
90
  route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
86
91
 
87
92
  rescue StandardError => error
88
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
93
+ @config.log_found_exception(__method__.to_s, error)
89
94
  end
90
95
 
91
96
  def route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
@@ -111,11 +116,11 @@ module SplitIoClient
111
116
  end
112
117
 
113
118
  def impression_router
114
- @impression_router ||= SplitIoClient::ImpressionRouter.new
119
+ @impression_router ||= SplitIoClient::ImpressionRouter.new(@config)
115
120
  end
116
121
 
117
122
  def track(key, traffic_type_name, event_type, value = nil, properties = nil)
118
- return false unless valid_client && SplitIoClient::Validators.valid_track_parameters(key, traffic_type_name, event_type, value, properties)
123
+ return false unless valid_client && @config.split_validator.valid_track_parameters(key, traffic_type_name, event_type, value, properties)
119
124
 
120
125
  properties_size = EVENT_AVERAGE_SIZE
121
126
 
@@ -123,16 +128,22 @@ module SplitIoClient
123
128
  properties, size = validate_properties(properties)
124
129
  properties_size += size
125
130
  if (properties_size > EVENTS_SIZE_THRESHOLD)
126
- SplitIoClient.configuration.logger.error("The maximum size allowed for the properties is #{EVENTS_SIZE_THRESHOLD}. Current is #{properties_size}. Event not queued")
131
+ @config.logger.error("The maximum size allowed for the properties is #{EVENTS_SIZE_THRESHOLD}. Current is #{properties_size}. Event not queued")
127
132
  return false
128
133
  end
129
134
  end
130
135
 
136
+ if ready? && !@splits_repository.traffic_type_exists(traffic_type_name)
137
+ @config.logger.warn("track: Traffic Type #{traffic_type_name} " \
138
+ "does not have any corresponding Splits in this environment, make sure you're tracking " \
139
+ 'your events to a valid traffic type defined in the Split console')
140
+ end
141
+
131
142
  begin
132
143
  @events_repository.add(key.to_s, traffic_type_name.downcase, event_type.to_s, (Time.now.to_f * 1000).to_i, value, properties, properties_size)
133
144
  true
134
145
  rescue StandardError => error
135
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
146
+ @config.log_found_exception(__method__.to_s, error)
136
147
  false
137
148
  end
138
149
  end
@@ -167,15 +178,19 @@ module SplitIoClient
167
178
  if (split_name.is_a?(String) || split_name.is_a?(Symbol)) && !split_name.empty?
168
179
  true
169
180
  elsif split_name.is_a?(String) && split_name.empty?
170
- SplitIoClient.configuration.logger.warn("#{calling_method}: you passed an empty split_name, split_name must be a non-empty String or a Symbol")
181
+ @config.logger.warn("#{calling_method}: you passed an empty split_name, split_name must be a non-empty String or a Symbol")
171
182
  false
172
183
  else
173
- SplitIoClient.configuration.logger.warn("#{calling_method}: you passed an invalid split_name, split_name must be a non-empty String or a Symbol")
184
+ @config.logger.warn("#{calling_method}: you passed an invalid split_name, split_name must be a non-empty String or a Symbol")
174
185
  false
175
186
  end
176
187
  end
177
188
  end
178
189
 
190
+ def block_until_ready(time = nil)
191
+ @sdk_blocker.block(time) if @sdk_blocker && !@sdk_blocker.ready?
192
+ end
193
+
179
194
  private
180
195
 
181
196
  def validate_properties(properties)
@@ -191,32 +206,32 @@ module SplitIoClient
191
206
  result[key] = value
192
207
  size += variable_size(value)
193
208
  else
194
- SplitIoClient.configuration.logger.warn("Property #{key} is of invalid type. Setting value to nil")
209
+ @config.logger.warn("Property #{key} is of invalid type. Setting value to nil")
195
210
  result[key] = nil
196
211
  end
197
212
  end
198
213
  }
199
214
 
200
- SplitIoClient.configuration.logger.warn('Event has more than 300 properties. Some of them will be trimmed when processed') if properties_count > 300
215
+ @config.logger.warn('Event has more than 300 properties. Some of them will be trimmed when processed') if properties_count > 300
201
216
 
202
217
  return fixed_properties, size
203
218
  end
204
219
 
205
220
  def valid_client
206
221
  if @destroyed
207
- SplitIoClient.configuration.logger.error('Client has already been destroyed - no calls possible')
222
+ @config.logger.error('Client has already been destroyed - no calls possible')
208
223
  return false
209
224
  end
210
- SplitIoClient.configuration.valid_mode
225
+ @config.valid_mode
211
226
  end
212
227
 
213
228
  def treatments(key, split_names, attributes = {}, calling_method = 'get_treatments')
214
- return nil unless SplitIoClient::Validators.valid_get_treatments_parameters(calling_method, split_names)
229
+ return nil unless @config.split_validator.valid_get_treatments_parameters(calling_method, split_names)
215
230
 
216
231
  sanitized_split_names = sanitize_split_names(calling_method, split_names)
217
232
 
218
233
  if sanitized_split_names.empty?
219
- SplitIoClient.configuration.logger.error("#{calling_method}: split_names must be a non-empty Array")
234
+ @config.logger.error("#{calling_method}: split_names must be a non-empty Array")
220
235
  return {}
221
236
  end
222
237
 
@@ -224,7 +239,7 @@ module SplitIoClient
224
239
  bucketing_key = bucketing_key ? bucketing_key.to_s : nil
225
240
  matching_key = matching_key ? matching_key.to_s : nil
226
241
 
227
- evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, true)
242
+ evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @config, true)
228
243
  start = Time.now
229
244
  treatments_labels_change_numbers =
230
245
  @splits_repository.get_splits(sanitized_split_names).each_with_object({}) do |(name, data), memo|
@@ -234,7 +249,7 @@ module SplitIoClient
234
249
  # Measure
235
250
  @adapter.metrics.time('sdk.' + calling_method, latency)
236
251
 
237
- unless SplitIoClient.configuration.disable_impressions
252
+ unless @config.disable_impressions
238
253
  time = (Time.now.to_f * 1000.0).to_i
239
254
  @impressions_repository.add_bulk(
240
255
  matching_key, bucketing_key, treatments_labels_change_numbers, time
@@ -269,38 +284,48 @@ module SplitIoClient
269
284
  key, split_name, attributes = {}, split_data = nil, store_impressions = true,
270
285
  multiple = false, evaluator = nil, calling_method = 'get_treatment'
271
286
  )
272
- control_treatment = { label: Engine::Models::Label::EXCEPTION, treatment: SplitIoClient::Engine::Models::Treatment::CONTROL, config: nil }
273
- parsed_control_treatment = parsed_treatment(multiple, control_treatment)
287
+ control_treatment = { treatment: Engine::Models::Treatment::CONTROL }
288
+
289
+ parsed_control_exception = parsed_treatment(multiple,
290
+ control_treatment.merge({ label: Engine::Models::Label::EXCEPTION }))
274
291
 
275
292
  bucketing_key, matching_key = keys_from_key(key)
276
293
 
277
- return parsed_control_treatment unless valid_client && SplitIoClient::Validators.valid_get_treatment_parameters(calling_method, key, split_name, matching_key, bucketing_key, attributes)
294
+ return parsed_control_exception unless valid_client && @config.split_validator.valid_get_treatment_parameters(calling_method, key, split_name, matching_key, bucketing_key, attributes)
278
295
 
279
296
  bucketing_key = bucketing_key ? bucketing_key.to_s : nil
280
297
  matching_key = matching_key.to_s
281
298
  sanitized_split_name = split_name.to_s.strip
282
299
 
283
300
  if split_name.to_s != sanitized_split_name
284
- SplitIoClient.configuration.logger.warn("#{calling_method}: split_name #{split_name} has extra whitespace, trimming")
301
+ @config.logger.warn("#{calling_method}: split_name #{split_name} has extra whitespace, trimming")
285
302
  split_name = sanitized_split_name
286
303
  end
287
304
 
288
- evaluator ||= Engine::Parser::Evaluator.new(@segments_repository, @splits_repository)
305
+ evaluator ||= Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @config)
289
306
 
290
307
  begin
291
308
  start = Time.now
292
309
 
293
310
  split = multiple ? split_data : @splits_repository.get_split(split_name)
294
311
 
295
- if split.nil?
296
- SplitIoClient.configuration.logger.warn("split_name: #{split_name} does not exist. Returning CONTROL")
297
- return parsed_control_treatment
312
+ if split.nil? && ready?
313
+ @config.logger.warn("#{calling_method}: you passed #{split_name} that " \
314
+ 'does not exist in this environment, please double check what Splits exist in the web console')
315
+
316
+ return parsed_treatment(multiple, control_treatment.merge({ label: Engine::Models::Label::NOT_FOUND }))
298
317
  end
299
318
 
300
319
  treatment_data =
320
+ if !split.nil? && ready?
301
321
  evaluator.call(
302
- { bucketing_key: bucketing_key, matching_key: matching_key }, split, attributes
303
- )
322
+ { bucketing_key: bucketing_key, matching_key: matching_key }, split, attributes
323
+ )
324
+ else
325
+ @config.logger.error("#{calling_method}: the SDK is not ready, the operation cannot be executed")
326
+
327
+ control_treatment.merge({ label: Engine::Models::Label::NOT_READY })
328
+ end
304
329
 
305
330
  latency = (Time.now - start) * 1000.0
306
331
  store_impression(split_name, matching_key, bucketing_key, treatment_data, store_impressions, attributes)
@@ -308,11 +333,11 @@ module SplitIoClient
308
333
  # Measure
309
334
  @adapter.metrics.time('sdk.' + calling_method, latency) unless multiple
310
335
  rescue StandardError => error
311
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
336
+ @config.log_found_exception(__method__.to_s, error)
312
337
 
313
338
  store_impression(split_name, matching_key, bucketing_key, control_treatment, store_impressions, attributes)
314
339
 
315
- return parsed_control_treatment
340
+ return parsed_control_exception
316
341
  end
317
342
 
318
343
  parsed_treatment(multiple, treatment_data)
@@ -321,5 +346,10 @@ module SplitIoClient
321
346
  def variable_size(value)
322
347
  value.is_a?(String) ? value.length : 0
323
348
  end
349
+
350
+ def ready?
351
+ return @sdk_blocker.ready? if @sdk_blocker
352
+ true
353
+ end
324
354
  end
325
355
  end