splitclient-rb 5.1.2.pre.rc21-java → 5.1.3.pre.rc1-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c06becb5108428c00b3ada0dd4404a22dd01c95
4
- data.tar.gz: 214b5ade2b8de67da2990b2370bc05936f7a7d87
3
+ metadata.gz: 86614a077b8bb2e11605c201e8d7ce74fa53af08
4
+ data.tar.gz: 5a775b16d37564ba6897dccd48d33472e7c4e1c3
5
5
  SHA512:
6
- metadata.gz: 0376aa2502f50ec6f986d67112ce44cb0c4be8484648d41b02c10ca3fda71dae087e0a43a960b261d922c0a4fb706d320dd655cba3a592cca56667f8c7a94a57
7
- data.tar.gz: b73de50c0959735428176349352694d2cc778390732a9bb6885a5089a35ad7e95171ffd7a58a7cad4a6f39858e9124b01979036d28f614e413371f87cc290f66
6
+ metadata.gz: 22d0552dfae11161414e2a624ffaf8a4e7d402914541109da17f71178474b6627e6b5c5ef71622e56190cbb1b30cec8cba60c2bf39099b0019f8705ed7c4f71a
7
+ data.tar.gz: 90e26ace99de500d55c05ddd9dc632b17e9d67bc8a1b5abbd1facae06110dfb8a43cb5443b9172293da7a25e1156a409b8e05406c7be5c1475ef307e33d70011
data/.gitignore CHANGED
@@ -44,5 +44,8 @@ lib/murmurhash/murmurhash.so
44
44
  ext/murmurhash/murmurhash.bundle
45
45
  ext/murmurhash/murmurhash.so
46
46
 
47
- #Ignore dump.rdb
47
+ # Ignore dump.rdb
48
48
  dump.rdb
49
+
50
+ # Ignore Mac OS generated files
51
+ .DS_Store
data/CHANGES.txt CHANGED
@@ -1,3 +1,9 @@
1
+ 5.1.3
2
+ - Add cache wrapper to treatments and segments.
3
+
4
+ 5.1.2 (October 26th, 2018)
5
+ - Add input validation for client API methods
6
+
1
7
  5.1.1 (October 4th, 2018)
2
8
  - Change get_treatments so that it sends a single latency metric
3
9
  - Removed unused call to Redis#scan when adding latencies
data/Detailed-README.md CHANGED
@@ -301,6 +301,14 @@ _To use Redis, include `redis-rb` in your app's Gemfile._
301
301
 
302
302
  *default value* = (your current hostname)
303
303
 
304
+ **cache_ttl** : Time to live in seconds for the memory cache values when using Redis.
305
+
306
+ *default value* = `5`
307
+
308
+ **max_cache_size** : Maximum number of items held in the memory cache values when using Redis. When cache is full an LRU strategy for pruning shall be used.
309
+
310
+ *default value* = `500`
311
+
304
312
  **redis_url** : Redis URL or hash with configuration for the SDK to connect to. See [Redis#initialize](https://www.rubydoc.info/github/redis/redis-rb/Redis%3Ainitialize) for detailed information.
305
313
 
306
314
  *default value* = `'redis://127.0.0.1:6379/0'`
data/NEWS CHANGED
@@ -1,3 +1,11 @@
1
+ 5.1.3
2
+
3
+ Add cache wrapper to treatments and segments.
4
+
5
+ 5.1.2
6
+
7
+ Add input validation for client API methods: get_treatment, get_treatments, track, manager
8
+
1
9
  5.1.1
2
10
 
3
11
  Reduces the number of calls to Redis when calling #client.get_treatments using such cache adapter.
@@ -2,11 +2,11 @@ require 'forwardable'
2
2
 
3
3
  require 'splitclient-rb/version'
4
4
 
5
- require 'splitclient-rb/exceptions/impressions_shutdown_exception'
6
- require 'splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception'
5
+ require 'splitclient-rb/exceptions'
7
6
  require 'splitclient-rb/cache/routers/impression_router'
8
7
  require 'splitclient-rb/cache/adapters/memory_adapters/map_adapter'
9
8
  require 'splitclient-rb/cache/adapters/memory_adapters/queue_adapter'
9
+ require 'splitclient-rb/cache/adapters/cache_adapter'
10
10
  require 'splitclient-rb/cache/adapters/memory_adapter'
11
11
  require 'splitclient-rb/cache/adapters/redis_adapter'
12
12
  require 'splitclient-rb/cache/repositories/repository'
@@ -80,6 +80,7 @@ require 'splitclient-rb/engine/models/split'
80
80
  require 'splitclient-rb/engine/models/label'
81
81
  require 'splitclient-rb/engine/models/treatment'
82
82
  require 'splitclient-rb/utilitites'
83
+ require 'splitclient-rb/validators'
83
84
 
84
85
  # C extension
85
86
  require 'murmurhash/murmurhash_mri'
@@ -0,0 +1,131 @@
1
+ require 'lru_redux'
2
+
3
+ module SplitIoClient
4
+ module Cache
5
+ module Adapters
6
+ class CacheAdapter
7
+ extend Forwardable
8
+ def_delegators :@adapter, :initialize_set, :set_bool, :pipelined
9
+
10
+ def initialize(adapter)
11
+ @cache = LruRedux::TTL::ThreadSafeCache.new(SplitIoClient.configuration.max_cache_size, SplitIoClient.configuration.cache_ttl)
12
+ @adapter = adapter
13
+ end
14
+
15
+ def delete(key)
16
+ @cache.delete(key)
17
+ @adapter.delete(key)
18
+ end
19
+
20
+ def clear(namespace_key)
21
+ @cache.clear
22
+ @adapter.clear(namespace_key)
23
+ end
24
+
25
+ def string(key)
26
+ value = get(key)
27
+ return value if value
28
+ value = @adapter.string(key)
29
+ add(key, value)
30
+ value
31
+ end
32
+
33
+ def set_string(key, value)
34
+ add(key, value)
35
+ @adapter.set_string(key, value)
36
+ end
37
+
38
+ def multiple_strings(keys)
39
+ cached_values = keys.each_with_object({}) do |key, memo|
40
+ memo[key] = get(key)
41
+ end
42
+
43
+ non_cached_keys = []
44
+ cached_values.delete_if{ |k,v| v.nil? ? non_cached_keys << k : false }
45
+
46
+ if non_cached_keys.any?
47
+ new_values = @adapter.multiple_strings(non_cached_keys)
48
+
49
+ new_values.keys.each do |key, value|
50
+ add(key, value)
51
+ end
52
+
53
+ cached_values.merge!(new_values)
54
+ end
55
+
56
+ cached_values
57
+ end
58
+
59
+ def find_strings_by_prefix(prefix)
60
+ @adapter.find_strings_by_prefix(prefix)
61
+ end
62
+
63
+ def exists?(key)
64
+ cached_value = get(key)
65
+ if cached_value.nil?
66
+ @adapter.exists?(key)
67
+ else
68
+ true
69
+ end
70
+ end
71
+
72
+ def add_to_set(key, values)
73
+ if values.is_a? Array
74
+ values.each { |value| add_to_map(key, value, 1) }
75
+ else
76
+ add_to_map(key, values, 1)
77
+ end
78
+ @adapter.add_to_set(key, values)
79
+ end
80
+
81
+ def in_set?(key, field)
82
+ cached_value = get(key)
83
+ if cached_value.nil?
84
+ return @adapter.in_set?(key, field)
85
+ end
86
+ cached_value.key?(field)
87
+ end
88
+
89
+ def get_set(key)
90
+ cached_value = get(key)
91
+ if cached_value.nil?
92
+ return @adapter.get_set(key)
93
+ end
94
+ cached_value.keys
95
+ end
96
+
97
+ def delete_from_set(key, fields)
98
+ cached_value = get(key)
99
+ if cached_value
100
+ if fields.is_a? Array
101
+ fields.each { |field| cached_value.delete(field) }
102
+ else
103
+ cached_value.delete(fields)
104
+ end
105
+ end
106
+
107
+ @adapter.delete_from_set(key, fields)
108
+ end
109
+
110
+ def initialize_map(key)
111
+ @cache[key] = Concurrent::Map.new
112
+ end
113
+
114
+ private
115
+
116
+ def add_to_map(key, field, value)
117
+ initialize_map(key) unless get(key)
118
+ get(key).put(field.to_s, value.to_s)
119
+ end
120
+
121
+ def add(key, value)
122
+ @cache[key] = value.to_s unless value.nil?
123
+ end
124
+
125
+ def get(key)
126
+ @cache[key]
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -7,7 +7,12 @@ module SplitIoClient
7
7
  attr_reader :adapter
8
8
 
9
9
  def initialize(adapter)
10
- @adapter = adapter
10
+ @adapter = case adapter.class.to_s
11
+ when 'SplitIoClient::Cache::Adapters::RedisAdapter'
12
+ SplitIoClient::Cache::Adapters::CacheAdapter.new(adapter)
13
+ else
14
+ adapter
15
+ end
11
16
  @adapter.set_bool(namespace_key('.ready'), false) unless SplitIoClient.configuration.mode == :consumer
12
17
  end
13
18
 
@@ -7,7 +7,12 @@ module SplitIoClient
7
7
  attr_reader :adapter
8
8
 
9
9
  def initialize(adapter)
10
- @adapter = adapter
10
+ @adapter = case adapter.class.to_s
11
+ when 'SplitIoClient::Cache::Adapters::RedisAdapter'
12
+ SplitIoClient::Cache::Adapters::CacheAdapter.new(adapter)
13
+ else
14
+ adapter
15
+ end
11
16
  unless SplitIoClient.configuration.mode == :consumer
12
17
  @adapter.set_string(namespace_key('.splits.till'), '-1')
13
18
  @adapter.initialize_map(namespace_key('.segments.registered'))
@@ -26,7 +31,7 @@ module SplitIoClient
26
31
 
27
32
  def get_splits(names)
28
33
  splits = {}
29
- split_names = names.reject(&:empty?).uniq.map { |name| namespace_key(".split.#{name}") }
34
+ split_names = names.map { |name| namespace_key(".split.#{name}") }
30
35
  splits.merge!(
31
36
  @adapter
32
37
  .multiple_strings(split_names)
@@ -1,4 +1,5 @@
1
1
  module SplitIoClient
2
+
2
3
  class SplitClient
3
4
  #
4
5
  # Creates a new split client instance that connects to split.io API.
@@ -17,11 +18,24 @@ module SplitIoClient
17
18
  end
18
19
 
19
20
  def get_treatments(key, split_names, attributes = {})
21
+
22
+ return nil unless SplitIoClient::Validators.valid_get_treatments_parameters(split_names)
23
+
24
+ sanitized_split_names = sanitize_split_names(split_names)
25
+
26
+ if sanitized_split_names.empty?
27
+ SplitIoClient.configuration.logger.warn('get_treatments: split_names is an empty array or has null values')
28
+ return {}
29
+ end
30
+
20
31
  bucketing_key, matching_key = keys_from_key(key)
32
+ bucketing_key = bucketing_key ? bucketing_key.to_s : nil
33
+ matching_key = matching_key ? matching_key.to_s : nil
34
+
21
35
  evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, true)
22
36
  start = Time.now
23
37
  treatments_labels_change_numbers =
24
- @splits_repository.get_splits(split_names).each_with_object({}) do |(name, data), memo|
38
+ @splits_repository.get_splits(sanitized_split_names).each_with_object({}) do |(name, data), memo|
25
39
  memo.merge!(name => get_treatment(key, name, attributes, data, false, true, evaluator))
26
40
  end
27
41
  latency = (Time.now - start) * 1000.0
@@ -34,13 +48,13 @@ module SplitIoClient
34
48
  matching_key, bucketing_key, treatments_labels_change_numbers, time
35
49
  )
36
50
 
37
- route_impressions(split_names, matching_key, bucketing_key, time, treatments_labels_change_numbers, attributes)
51
+ route_impressions(sanitized_split_names, matching_key, bucketing_key, time, treatments_labels_change_numbers, attributes)
38
52
  end
39
53
 
40
- split_names = treatments_labels_change_numbers.keys
54
+ split_names_keys = treatments_labels_change_numbers.keys
41
55
  treatments = treatments_labels_change_numbers.values.map { |v| v[:treatment] }
42
56
 
43
- Hash[split_names.zip(treatments)]
57
+ Hash[split_names_keys.zip(treatments)]
44
58
  end
45
59
 
46
60
  #
@@ -59,68 +73,43 @@ module SplitIoClient
59
73
  key, split_name, attributes = {}, split_data = nil, store_impressions = true,
60
74
  multiple = false, evaluator = nil
61
75
  )
62
- bucketing_key, matching_key = keys_from_key(key)
63
- treatment_data = { label: Engine::Models::Label::DEFINITION_NOT_FOUND, treatment: SplitIoClient::Engine::Models::Treatment::CONTROL }
64
- evaluator ||= Engine::Parser::Evaluator.new(@segments_repository, @splits_repository)
76
+ control_treatment = { label: Engine::Models::Label::EXCEPTION, treatment: SplitIoClient::Engine::Models::Treatment::CONTROL }
77
+ parsed_control_treatment = parsed_treatment(multiple, control_treatment)
65
78
 
66
- if matching_key.nil?
67
- SplitIoClient.configuration.logger.warn('matching_key was null for split_name: ' + split_name.to_s)
68
- return parsed_treatment(multiple, treatment_data)
69
- end
79
+ bucketing_key, matching_key = keys_from_key(key)
70
80
 
71
- if split_name.nil?
72
- SplitIoClient.configuration.logger.warn('split_name was null for key: ' + key)
73
- return parsed_treatment(multiple, treatment_data)
74
- end
81
+ return parsed_control_treatment unless SplitIoClient::Validators.valid_get_treatment_parameters(key, split_name, matching_key, bucketing_key)
75
82
 
76
- start = Time.now
83
+ bucketing_key = bucketing_key ? bucketing_key.to_s : nil
84
+ matching_key = matching_key.to_s
85
+ evaluator ||= Engine::Parser::Evaluator.new(@segments_repository, @splits_repository)
77
86
 
78
87
  begin
88
+ start = Time.now
89
+
79
90
  split = multiple ? split_data : @splits_repository.get_split(split_name)
80
91
 
81
92
  if split.nil?
82
- SplitIoClient.configuration.logger.debug("split_name: #{split_name} does not exist. Returning CONTROL")
83
- return parsed_treatment(multiple, treatment_data)
84
- else
85
- treatment_data =
86
- evaluator.call(
87
- { bucketing_key: bucketing_key, matching_key: matching_key }, split, attributes
88
- )
93
+ SplitIoClient.configuration.logger.warn("split_name: #{split_name} does not exist. Returning CONTROL")
94
+ return parsed_control_treatment
89
95
  end
90
- rescue StandardError => error
91
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
92
96
 
93
- store_impression(
94
- split_name, matching_key, bucketing_key,
95
- {
96
- treatment: SplitIoClient::Engine::Models::Treatment::CONTROL,
97
- label: SplitIoClient::Engine::Models::Label::EXCEPTION
98
- },
99
- store_impressions, attributes
97
+ treatment_data =
98
+ evaluator.call(
99
+ { bucketing_key: bucketing_key, matching_key: matching_key }, split, attributes
100
100
  )
101
101
 
102
- return parsed_treatment(multiple, treatment_data)
103
- end
104
-
105
- begin
106
102
  latency = (Time.now - start) * 1000.0
107
- split && store_impression(split_name, matching_key, bucketing_key, treatment_data, store_impressions, attributes)
103
+ store_impression(split_name, matching_key, bucketing_key, treatment_data, store_impressions, attributes)
108
104
 
109
105
  # Measure
110
106
  @adapter.metrics.time('sdk.get_treatment', latency) unless multiple
111
107
  rescue StandardError => error
112
108
  SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
113
109
 
114
- store_impression(
115
- split_name, matching_key, bucketing_key,
116
- {
117
- treatment: SplitIoClient::Engine::Models::Treatment::CONTROL,
118
- label: SplitIoClient::Engine::Models::Label::EXCEPTION
119
- },
120
- store_impressions, attributes
121
- )
110
+ store_impression(split_name, matching_key, bucketing_key, control_treatment, store_impressions, attributes)
122
111
 
123
- return parsed_treatment(multiple, treatment_data)
112
+ return parsed_control_treatment
124
113
  end
125
114
 
126
115
  parsed_treatment(multiple, treatment_data)
@@ -188,16 +177,23 @@ module SplitIoClient
188
177
  @impression_router ||= SplitIoClient::ImpressionRouter.new
189
178
  end
190
179
 
191
- def track(key, traffic_type, event_type, value = nil)
192
- @events_repository.add(key, traffic_type, event_type, (Time.now.to_f * 1000).to_i, value)
180
+ def track(key, traffic_type_name, event_type, value = nil)
181
+ return false unless SplitIoClient::Validators.valid_track_parameters(key, traffic_type_name, event_type, value)
182
+ begin
183
+ @events_repository.add(key.to_s, traffic_type_name, event_type.to_s, (Time.now.to_f * 1000).to_i, value)
184
+ true
185
+ rescue StandardError => error
186
+ SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
187
+ false
188
+ end
193
189
  end
194
190
 
195
191
  def keys_from_key(key)
196
192
  case key.class.to_s
197
193
  when 'Hash'
198
- key.values_at(:bucketing_key, :matching_key).map { |k| k.nil? ? nil : k.to_s }
194
+ key.values_at(:bucketing_key, :matching_key).map { |k| k.nil? ? nil : k }
199
195
  else
200
- [nil, key].map { |k| k.nil? ? nil : k.to_s }
196
+ [nil, key].map { |k| k.nil? ? nil : k }
201
197
  end
202
198
  end
203
199
 
@@ -212,5 +208,16 @@ module SplitIoClient
212
208
  treatment_data[:treatment]
213
209
  end
214
210
  end
211
+
212
+ def sanitize_split_names(split_names)
213
+ split_names.compact.uniq.select do |split_name|
214
+ if split_name.is_a?(String) && !split_name.empty?
215
+ true
216
+ else
217
+ SplitIoClient.configuration.logger.warn('get_treatments: split_name has to be a non empty string')
218
+ false
219
+ end
220
+ end
221
+ end
215
222
  end
216
223
  end
@@ -4,5 +4,4 @@ class SplitIoClient::Engine::Models::Label
4
4
  EXCEPTION = 'exception'.freeze
5
5
  KILLED = 'killed'.freeze
6
6
  NOT_IN_SPLIT = 'not in split'.freeze
7
- DEFINITION_NOT_FOUND = 'definition not found'.freeze
8
7
  end
@@ -0,0 +1,7 @@
1
+ module SplitIoClient
2
+ class SplitIoError < StandardError; end
3
+
4
+ class ImpressionShutdownException < SplitIoError; end
5
+
6
+ class SDKBlockerTimeoutExpiredException < SplitIoError; end
7
+ end
@@ -43,7 +43,7 @@ module SplitIoClient
43
43
  #
44
44
  # @returns a split view
45
45
  def split(split_name)
46
- return unless @splits_repository
46
+ return unless @splits_repository && SplitIoClient::Validators.valid_split_parameters(split_name)
47
47
 
48
48
  split = @splits_repository.get_split(split_name)
49
49
 
@@ -63,7 +63,6 @@ module SplitIoClient
63
63
  treatments = []
64
64
  end
65
65
 
66
-
67
66
  {
68
67
  name: name,
69
68
  traffic_type_name: split[:trafficTypeName],
@@ -33,6 +33,8 @@ module SplitIoClient
33
33
  # @option opts [Int] :impressions_queue_size Size of the impressions queue in the memory repository. Once reached, newer impressions will be dropped
34
34
  # @option opts [Int] :impressions_bulk_size Max number of impressions to be sent to the backend on each post
35
35
  # @option opts [#log] :impression_listener this object will capture all impressions and process them through `#log`
36
+ # @option opts [Int] :cache_ttl Time to live in seconds for the memory cache values when using Redis.
37
+ # @option opts [Int] :max_cache_size Max number of items to be held in the memory cache before prunning when using Redis.
36
38
  # @return [type] SplitConfig with configuration options
37
39
  def initialize(opts = {})
38
40
  @base_uri = (opts[:base_uri] || SplitConfig.default_base_uri).chomp('/')
@@ -70,6 +72,9 @@ module SplitIoClient
70
72
  @machine_name = opts[:machine_name] || SplitConfig.machine_hostname
71
73
  @machine_ip = opts[:machine_ip] || SplitConfig.machine_ip
72
74
 
75
+ @cache_ttl = opts[:cache_ttl] || SplitConfig.cache_ttl
76
+ @max_cache_size = opts[:max_cache_size] || SplitConfig.max_cache_size
77
+
73
78
  @language = opts[:language] || 'ruby'
74
79
  @version = opts[:version] || SplitIoClient::VERSION
75
80
 
@@ -176,6 +181,9 @@ module SplitIoClient
176
181
  attr_accessor :machine_ip
177
182
  attr_accessor :machine_name
178
183
 
184
+ attr_accessor :cache_ttl
185
+ attr_accessor :max_cache_size
186
+
179
187
  attr_accessor :language
180
188
  attr_accessor :version
181
189
 
@@ -357,6 +365,21 @@ module SplitIoClient
357
365
  false
358
366
  end
359
367
 
368
+ #
369
+ # The default cache time to live
370
+ #
371
+ # @return [boolean]
372
+ def self.cache_ttl
373
+ 5
374
+ end
375
+
376
+ # The default max cache size
377
+ #
378
+ # @return [boolean]
379
+ def self.max_cache_size
380
+ 500
381
+ end
382
+
360
383
  #
361
384
  # custom logger of exceptions
362
385
  #
@@ -0,0 +1,185 @@
1
+ module SplitIoClient
2
+ module Validators
3
+ extend self
4
+
5
+ def valid_get_treatment_parameters(key, split_name, matching_key, bucketing_key)
6
+ valid_key?(key) && valid_split_name?(split_name) && valid_matching_key?(matching_key) && valid_bucketing_key?(bucketing_key)
7
+ end
8
+
9
+ def valid_get_treatments_parameters(split_names)
10
+ valid_split_names?(split_names)
11
+ end
12
+
13
+ def valid_track_parameters(key, traffic_type_name, event_type, value)
14
+ valid_track_key?(key) && valid_traffic_type_name?(traffic_type_name) && valid_event_type?(event_type) && valid_value?(value)
15
+ end
16
+
17
+ def valid_split_parameters(split_name)
18
+ valid_split_name?(split_name, :split)
19
+ end
20
+
21
+ private
22
+
23
+ def string?(value)
24
+ value.is_a?(String) || value.is_a?(Symbol)
25
+ end
26
+
27
+ def number_or_string?(value)
28
+ value.is_a?(Numeric) || string?(value)
29
+ end
30
+
31
+ def log_nil(key, method)
32
+ SplitIoClient.configuration.logger.error("#{method}: #{key} cannot be nil")
33
+ end
34
+
35
+ def log_string(key, method)
36
+ SplitIoClient.configuration.logger.error("#{method}: #{key} must be a String or a Symbol")
37
+ end
38
+
39
+ def log_number_or_string(key, method)
40
+ SplitIoClient.configuration.logger.error("#{method}: #{key} must be a String")
41
+ end
42
+
43
+ def log_convert_numeric(key, method)
44
+ SplitIoClient.configuration.logger.warn("#{method}: #{key} is not of type String, converting to String")
45
+ end
46
+
47
+ def valid_split_name?(split_name, method=:get_treatment)
48
+ if split_name.nil?
49
+ log_nil(:split_name, method)
50
+ return false
51
+ end
52
+
53
+ unless string?(split_name)
54
+ log_string(:split_name, method)
55
+ return false
56
+ end
57
+
58
+ return true
59
+ end
60
+
61
+ def valid_key?(key)
62
+ if key.nil?
63
+ log_nil(:key, :get_treatment)
64
+ return false
65
+ end
66
+
67
+ return true
68
+ end
69
+
70
+ def valid_matching_key?(matching_key)
71
+ if matching_key.nil?
72
+ log_nil(:matching_key, :get_treatment)
73
+ return false
74
+ end
75
+
76
+ unless number_or_string?(matching_key)
77
+ log_number_or_string(:matching_key, :get_treatment)
78
+ return false
79
+ end
80
+
81
+ if matching_key.is_a? Numeric
82
+ log_convert_numeric(:matching_key, :get_treatment)
83
+ end
84
+
85
+ return true
86
+ end
87
+
88
+ def valid_bucketing_key?(bucketing_key)
89
+ if bucketing_key.nil?
90
+ SplitIoClient.configuration.logger.warn('get_treatment: key object should have bucketing_key set')
91
+ return true
92
+ end
93
+
94
+ unless number_or_string?(bucketing_key)
95
+ log_number_or_string(:bucketing_key, :get_treatment)
96
+ return false
97
+ end
98
+
99
+ if bucketing_key.is_a? Numeric
100
+ log_convert_numeric(:bucketing_key, :get_treatment)
101
+ end
102
+
103
+ return true
104
+ end
105
+
106
+ def valid_split_names?(split_names)
107
+ if split_names.nil?
108
+ log_nil(:split_names, :get_treatments)
109
+ return false
110
+ end
111
+
112
+ unless split_names.is_a? Array
113
+ SplitIoClient.configuration.logger.warn('get_treatments: split_names must be an Array')
114
+ return false
115
+ end
116
+
117
+ return true
118
+ end
119
+
120
+ def valid_track_key?(key)
121
+ if key.nil?
122
+ log_nil(:key, :track)
123
+ return false
124
+ end
125
+
126
+ unless number_or_string?(key)
127
+ log_number_or_string(:key, :track)
128
+ return false
129
+ end
130
+
131
+ if key.is_a? Numeric
132
+ log_convert_numeric(:key, :track)
133
+ end
134
+
135
+ return true
136
+ end
137
+
138
+ def valid_event_type?(event_type)
139
+ if event_type.nil?
140
+ log_nil(:event_type, :track)
141
+ return false
142
+ end
143
+
144
+ unless string?(event_type)
145
+ log_string(:event_type, :track)
146
+ return false
147
+ end
148
+
149
+ if (event_type.to_s =~ /[a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}/).nil?
150
+ SplitIoClient.configuration.logger.error('track: event_type must adhere to [a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}')
151
+ return false
152
+ end
153
+
154
+ return true
155
+ end
156
+
157
+ def valid_traffic_type_name?(traffic_type_name)
158
+ if traffic_type_name.nil?
159
+ log_nil(:traffic_type_name, :track)
160
+ return false
161
+ end
162
+
163
+ unless string?(traffic_type_name)
164
+ log_string(:traffic_type_name, :track)
165
+ return false
166
+ end
167
+
168
+ if traffic_type_name.empty?
169
+ SplitIoClient.configuration.logger.error('track: traffic_type_name must not be an empty String')
170
+ return false
171
+ end
172
+
173
+ return true
174
+ end
175
+
176
+ def valid_value?(value)
177
+ unless value.is_a?(Numeric) || value.nil?
178
+ SplitIoClient.configuration.logger.error('track: value must be a number')
179
+ return false
180
+ end
181
+
182
+ return true
183
+ end
184
+ end
185
+ end
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '5.1.2.pre.rc21'
2
+ VERSION = '5.1.3.pre.rc1'
3
3
  end
@@ -46,11 +46,13 @@ Gem::Specification.new do |spec|
46
46
  spec.add_development_dependency 'rspec'
47
47
  spec.add_development_dependency 'rubocop', '0.59.0'
48
48
  spec.add_development_dependency 'simplecov'
49
+ spec.add_development_dependency 'timecop'
49
50
  spec.add_development_dependency 'webmock'
50
51
 
51
52
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
52
53
  spec.add_runtime_dependency 'faraday', '>= 0.8'
53
54
  spec.add_runtime_dependency 'json', '>= 1.8'
55
+ spec.add_runtime_dependency 'lru_redux'
54
56
  spec.add_runtime_dependency 'net-http-persistent', '~> 2.9'
55
57
  spec.add_runtime_dependency 'redis', '>= 3.2'
56
58
  spec.add_runtime_dependency 'thread_safe', '>= 0.3'
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: 5.1.2.pre.rc21
4
+ version: 5.1.3.pre.rc1
5
5
  platform: java
6
6
  authors:
7
7
  - Split Software
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-18 00:00:00.000000000 Z
11
+ date: 2018-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ name: timecop
146
+ prerelease: false
147
+ type: :development
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  requirement: !ruby/object:Gem::Requirement
141
155
  requirements:
@@ -192,6 +206,20 @@ dependencies:
192
206
  - - ">="
193
207
  - !ruby/object:Gem::Version
194
208
  version: '1.8'
209
+ - !ruby/object:Gem::Dependency
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ name: lru_redux
216
+ prerelease: false
217
+ type: :runtime
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
195
223
  - !ruby/object:Gem::Dependency
196
224
  requirement: !ruby/object:Gem::Requirement
197
225
  requirements:
@@ -257,6 +285,7 @@ files:
257
285
  - lib/murmurhash/murmurhash.jar
258
286
  - lib/murmurhash/murmurhash_mri.rb
259
287
  - lib/splitclient-rb.rb
288
+ - lib/splitclient-rb/cache/adapters/cache_adapter.rb
260
289
  - lib/splitclient-rb/cache/adapters/memory_adapter.rb
261
290
  - lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb
262
291
  - lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb
@@ -321,8 +350,7 @@ files:
321
350
  - lib/splitclient-rb/engine/parser/evaluator.rb
322
351
  - lib/splitclient-rb/engine/parser/partition.rb
323
352
  - lib/splitclient-rb/engine/parser/split_adapter.rb
324
- - lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb
325
- - lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb
353
+ - lib/splitclient-rb/exceptions.rb
326
354
  - lib/splitclient-rb/localhost_split_factory.rb
327
355
  - lib/splitclient-rb/localhost_utils.rb
328
356
  - lib/splitclient-rb/managers/localhost_split_manager.rb
@@ -332,6 +360,7 @@ files:
332
360
  - lib/splitclient-rb/split_factory_builder.rb
333
361
  - lib/splitclient-rb/split_logger.rb
334
362
  - lib/splitclient-rb/utilitites.rb
363
+ - lib/splitclient-rb/validators.rb
335
364
  - lib/splitclient-rb/version.rb
336
365
  - splitclient-rb.gemspec
337
366
  - splitio.yml.example
@@ -1,4 +0,0 @@
1
- module SplitIoClient
2
- class ImpressionShutdownException < StandardError
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module SplitIoClient
2
- class SDKBlockerTimeoutExpiredException < StandardError
3
- end
4
- end