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

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
  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