splitclient-rb 6.0.1 → 6.1.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -1
  3. data/.simplecov +1 -0
  4. data/README.md +2 -2
  5. data/lib/splitclient-rb.rb +1 -0
  6. data/lib/splitclient-rb/clients/split_client.rb +30 -9
  7. data/lib/splitclient-rb/engine/api/client.rb +8 -9
  8. data/lib/splitclient-rb/engine/api/events.rb +4 -2
  9. data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +10 -8
  10. data/lib/splitclient-rb/engine/api/impressions.rb +4 -2
  11. data/lib/splitclient-rb/engine/api/metrics.rb +5 -5
  12. data/lib/splitclient-rb/engine/api/segments.rb +5 -1
  13. data/lib/splitclient-rb/engine/api/splits.rb +4 -4
  14. data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +8 -13
  15. data/lib/splitclient-rb/engine/matchers/between_matcher.rb +12 -23
  16. data/lib/splitclient-rb/engine/matchers/combiners.rb +3 -1
  17. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +16 -24
  18. data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +10 -7
  19. data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +7 -6
  20. data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +19 -8
  21. data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +8 -3
  22. data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +21 -6
  23. data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +17 -8
  24. data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +11 -23
  25. data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +7 -6
  26. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +13 -25
  27. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +13 -25
  28. data/lib/splitclient-rb/engine/matchers/matcher.rb +30 -0
  29. data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +6 -2
  30. data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +8 -22
  31. data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +10 -7
  32. data/lib/splitclient-rb/engine/matchers/set_matcher.rb +7 -1
  33. data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +18 -5
  34. data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +7 -25
  35. data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +33 -35
  36. data/lib/splitclient-rb/managers/split_manager.rb +10 -3
  37. data/lib/splitclient-rb/split_config.rb +34 -9
  38. data/lib/splitclient-rb/split_factory.rb +27 -0
  39. data/lib/splitclient-rb/validators.rb +104 -36
  40. data/lib/splitclient-rb/version.rb +1 -1
  41. metadata +6 -4
@@ -1,5 +1,6 @@
1
1
  module SplitIoClient
2
2
  class SplitFactory
3
+ ROOT_PROCESS_ID = Process.pid
3
4
  include SplitIoClient::Cache::Repositories
4
5
  include SplitIoClient::Cache::Stores
5
6
 
@@ -25,7 +26,21 @@ module SplitIoClient
25
26
  @client = SplitClient.new(@api_key, @adapter, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @events_repository)
26
27
  @manager = SplitManager.new(@api_key, @adapter, @splits_repository)
27
28
 
29
+ validate_api_key
30
+
28
31
  @sdk_blocker.block if SplitIoClient.configuration.block_until_ready > 0
32
+
33
+
34
+ at_exit do
35
+ unless ENV['SPLITCLIENT_ENV'] == 'test'
36
+ if (Process.pid == ROOT_PROCESS_ID)
37
+ SplitIoClient.configuration.logger.info('Split SDK shutdown started...')
38
+ @client.destroy
39
+ stop!
40
+ SplitIoClient.configuration.logger.info('Split SDK shutdown complete')
41
+ end
42
+ end
43
+ end
29
44
  end
30
45
 
31
46
  def start!
@@ -65,5 +80,17 @@ module SplitIoClient
65
80
  end
66
81
 
67
82
  alias resume! start!
83
+
84
+ private
85
+
86
+ def validate_api_key
87
+ if(@api_key.nil?)
88
+ SplitIoClient.configuration.logger.error('Factory Instantiation: you passed a nil api_key, api_key must be a non-empty String')
89
+ SplitIoClient.configuration.valid_mode = false
90
+ elsif (@api_key.empty?)
91
+ SplitIoClient.configuration.logger.error('Factory Instantiation: you passed and empty api_key, api_key must be a non-empty String')
92
+ SplitIoClient.configuration.valid_mode = false
93
+ end
94
+ end
68
95
  end
69
96
  end
@@ -4,11 +4,12 @@ module SplitIoClient
4
4
  module Validators
5
5
  extend self
6
6
 
7
- def valid_get_treatment_parameters(key, split_name, matching_key, bucketing_key)
7
+ def valid_get_treatment_parameters(key, split_name, matching_key, bucketing_key, attributes)
8
8
  valid_key?(key) &&
9
9
  valid_split_name?(split_name) &&
10
10
  valid_matching_key?(matching_key) &&
11
- valid_bucketing_key?(key, bucketing_key)
11
+ valid_bucketing_key?(key, bucketing_key) &&
12
+ valid_attributes?(attributes)
12
13
  end
13
14
 
14
15
  def valid_get_treatments_parameters(split_names)
@@ -26,30 +27,45 @@ module SplitIoClient
26
27
  valid_split_name?(split_name, :split)
27
28
  end
28
29
 
30
+ def valid_matcher_arguments(args)
31
+ return false if !args.key?(:attributes) && !args.key?(:value)
32
+ return false if args.key?(:value) && args[:value].nil?
33
+ return false if args.key?(:attributes) && args[:attributes].nil?
34
+ true
35
+ end
36
+
29
37
  private
30
38
 
31
39
  def string?(value)
32
40
  value.is_a?(String) || value.is_a?(Symbol)
33
41
  end
34
42
 
43
+ def empty_string?(value)
44
+ value.is_a?(String) && value.empty?
45
+ end
46
+
35
47
  def number_or_string?(value)
36
- value.is_a?(Numeric) || string?(value)
48
+ (value.is_a?(Numeric) && !value.to_f.nan?) || string?(value)
37
49
  end
38
50
 
39
51
  def log_nil(key, method)
40
- SplitIoClient.configuration.logger.error("#{method}: #{key} cannot be nil")
52
+ SplitIoClient.configuration.logger.error("#{method}: you passed a nil #{key}, #{key} must be a non-empty String or a Symbol")
41
53
  end
42
54
 
43
- def log_string(key, method)
44
- SplitIoClient.configuration.logger.error("#{method}: #{key} must be a String or a Symbol")
55
+ def log_empty_string(key, method)
56
+ SplitIoClient.configuration.logger.error("#{method}: you passed an empty #{key}, #{key} must be a non-empty String or a Symbol")
45
57
  end
46
58
 
47
- def log_number_or_string(key, method)
48
- SplitIoClient.configuration.logger.error("#{method}: #{key} must be a String")
59
+ def log_invalid_type(key, method)
60
+ SplitIoClient.configuration.logger.error("#{method}: you passed an invalid #{key} type, #{key} must be a non-empty String or a Symbol")
49
61
  end
50
62
 
51
- def log_convert_numeric(key, method)
52
- SplitIoClient.configuration.logger.warn("#{method}: #{key} is not of type String, converting to String")
63
+ def log_convert_numeric(key, method, value)
64
+ SplitIoClient.configuration.logger.warn("#{method}: #{key} \"#{value}\" is not of type String, converting")
65
+ end
66
+
67
+ def log_key_too_long(key, method)
68
+ SplitIoClient.configuration.logger.error("#{method}: #{key} is too long - must be #{SplitIoClient.configuration.max_key_size} characters or less")
53
69
  end
54
70
 
55
71
  def valid_split_name?(split_name, method = :get_treatment)
@@ -59,7 +75,12 @@ module SplitIoClient
59
75
  end
60
76
 
61
77
  unless string?(split_name)
62
- log_string(:split_name, method)
78
+ log_invalid_type(:split_name, method)
79
+ return false
80
+ end
81
+
82
+ if empty_string?(split_name)
83
+ log_empty_string(:split_name, method)
63
84
  return false
64
85
  end
65
86
 
@@ -82,41 +103,65 @@ module SplitIoClient
82
103
  end
83
104
 
84
105
  unless number_or_string?(matching_key)
85
- log_number_or_string(:matching_key, :get_treatment)
106
+ log_invalid_type(:matching_key, :get_treatment)
86
107
  return false
87
108
  end
88
109
 
89
- log_convert_numeric(:matching_key, :get_treatment) if matching_key.is_a? Numeric
110
+ if empty_string?(matching_key)
111
+ log_empty_string(:matching_key, :get_treatment)
112
+ return false
113
+ end
114
+
115
+ log_convert_numeric(:matching_key, :get_treatment, matching_key) if matching_key.is_a? Numeric
116
+
117
+ if matching_key.size > SplitIoClient.configuration.max_key_size
118
+ log_key_too_long(:matching_key, :get_treatment)
119
+ return false
120
+ end
90
121
 
91
122
  true
92
123
  end
93
124
 
94
125
  def valid_bucketing_key?(key, bucketing_key)
95
- if bucketing_key.nil?
96
- if key.is_a? Hash
97
- SplitIoClient.configuration.logger.warn('get_treatment: key object should have bucketing_key set')
126
+ if key.is_a? Hash
127
+ if bucketing_key.nil?
128
+ log_nil(:bucketing_key, :get_treatment)
129
+ return false
98
130
  end
99
- return true
100
- end
101
131
 
102
- unless number_or_string?(bucketing_key)
103
- log_number_or_string(:bucketing_key, :get_treatment)
104
- return false
105
- end
132
+ unless number_or_string?(bucketing_key)
133
+ log_invalid_type(:bucketing_key, :get_treatment)
134
+ return false
135
+ end
106
136
 
107
- log_convert_numeric(:bucketing_key, :get_treatment) if bucketing_key.is_a? Numeric
137
+ if empty_string?(bucketing_key)
138
+ log_empty_string(:bucketing_key, :get_treatment)
139
+ return false
140
+ end
141
+
142
+ log_convert_numeric(:bucketing_key, :get_treatment, bucketing_key) if bucketing_key.is_a? Numeric
143
+
144
+ if bucketing_key.size > SplitIoClient.configuration.max_key_size
145
+ log_key_too_long(:bucketing_key, :get_treatment)
146
+ return false
147
+ end
148
+ end
108
149
 
109
150
  true
110
151
  end
111
152
 
112
153
  def valid_split_names?(split_names)
113
- if split_names.nil?
114
- log_nil(:split_names, :get_treatments)
154
+ unless !split_names.nil? && split_names.is_a?(Array)
155
+ SplitIoClient.configuration.logger.error('get_treatments: split_names must be a non-empty Array')
115
156
  return false
116
157
  end
117
158
 
118
- unless split_names.is_a? Array
119
- SplitIoClient.configuration.logger.warn('get_treatments: split_names must be an Array')
159
+ true
160
+ end
161
+
162
+ def valid_attributes?(attributes)
163
+ unless attributes.nil? || attributes.is_a?(Hash)
164
+ SplitIoClient.configuration.logger.error('get_treatment: attributes must be of type Hash')
120
165
  return false
121
166
  end
122
167
 
@@ -130,11 +175,21 @@ module SplitIoClient
130
175
  end
131
176
 
132
177
  unless number_or_string?(key)
133
- log_number_or_string(:key, :track)
178
+ log_invalid_type(:key, :track)
134
179
  return false
135
180
  end
136
181
 
137
- log_convert_numeric(:key, :track) if key.is_a? Numeric
182
+ if empty_string?(key)
183
+ log_empty_string(:key, :track)
184
+ return false
185
+ end
186
+
187
+ log_convert_numeric(:key, :track, key) if key.is_a? Numeric
188
+
189
+ if key.size > SplitIoClient.configuration.max_key_size
190
+ log_key_too_long(:key, :track)
191
+ return false
192
+ end
138
193
 
139
194
  true
140
195
  end
@@ -146,12 +201,20 @@ module SplitIoClient
146
201
  end
147
202
 
148
203
  unless string?(event_type)
149
- log_string(:event_type, :track)
204
+ log_invalid_type(:event_type, :track)
150
205
  return false
151
206
  end
152
207
 
153
- if (event_type.to_s =~ /[a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}/).nil?
154
- SplitIoClient.configuration.logger.error('track: event_type must adhere to [a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}')
208
+ if event_type.empty?
209
+ log_empty_string(:event_type, :track)
210
+ return false
211
+ end
212
+
213
+ if (event_type.to_s =~ /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/).nil?
214
+ SplitIoClient.configuration.logger.error("track: you passed '#{event_type}', " \
215
+ 'event_type must adhere to the regular expression ^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$. ' \
216
+ 'This means an event name must be alphanumeric, cannot be more than 80 characters long, ' \
217
+ 'and can only include a dash, underscore, period, or colon as separators of alphanumeric characters')
155
218
  return false
156
219
  end
157
220
 
@@ -165,21 +228,26 @@ module SplitIoClient
165
228
  end
166
229
 
167
230
  unless string?(traffic_type_name)
168
- log_string(:traffic_type_name, :track)
231
+ log_invalid_type(:traffic_type_name, :track)
169
232
  return false
170
233
  end
171
234
 
172
235
  if traffic_type_name.empty?
173
- SplitIoClient.configuration.logger.error('track: traffic_type_name must not be an empty String')
236
+ log_empty_string(:traffic_type_name, :track)
174
237
  return false
175
238
  end
176
239
 
240
+ unless traffic_type_name == traffic_type_name.downcase
241
+ SplitIoClient.configuration.logger.warn('track: traffic_type_name should be all lowercase - ' \
242
+ 'converting string to lowercase')
243
+ end
244
+
177
245
  true
178
246
  end
179
247
 
180
248
  def valid_value?(value)
181
- unless value.is_a?(Numeric) || value.nil?
182
- SplitIoClient.configuration.logger.error('track: value must be a number')
249
+ unless (value.is_a?(Numeric) && !value.to_f.nan?) || value.nil?
250
+ SplitIoClient.configuration.logger.error('track: value must be Numeric')
183
251
  return false
184
252
  end
185
253
 
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '6.0.1'
2
+ VERSION = '6.1.0.pre.rc1'
3
3
  end
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: 6.0.1
4
+ version: 6.1.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: 2019-01-07 00:00:00.000000000 Z
11
+ date: 2019-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allocation_stats
@@ -272,6 +272,7 @@ extra_rdoc_files: []
272
272
  files:
273
273
  - ".gitignore"
274
274
  - ".rubocop.yml"
275
+ - ".simplecov"
275
276
  - CHANGES.txt
276
277
  - Detailed-README.md
277
278
  - Gemfile
@@ -336,6 +337,7 @@ files:
336
337
  - lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb
337
338
  - lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb
338
339
  - lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb
340
+ - lib/splitclient-rb/engine/matchers/matcher.rb
339
341
  - lib/splitclient-rb/engine/matchers/matches_string_matcher.rb
340
342
  - lib/splitclient-rb/engine/matchers/negation_matcher.rb
341
343
  - lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb
@@ -383,9 +385,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
383
385
  version: '0'
384
386
  required_rubygems_version: !ruby/object:Gem::Requirement
385
387
  requirements:
386
- - - ">="
388
+ - - ">"
387
389
  - !ruby/object:Gem::Version
388
- version: '0'
390
+ version: 1.3.1
389
391
  requirements: []
390
392
  rubyforge_project:
391
393
  rubygems_version: 2.7.6