splitclient-rb 5.1.2.pre.rc21 → 5.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/CHANGES.txt +3 -0
- data/NEWS +4 -0
- data/lib/splitclient-rb.rb +2 -2
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +1 -1
- data/lib/splitclient-rb/clients/split_client.rb +57 -50
- data/lib/splitclient-rb/engine/models/label.rb +0 -1
- data/lib/splitclient-rb/exceptions.rb +7 -0
- data/lib/splitclient-rb/managers/split_manager.rb +1 -2
- data/lib/splitclient-rb/validators.rb +185 -0
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +6 -6
- data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +0 -4
- data/lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aac78f1a43b52720c039260ceb19474cb8fd03fd473cbf0054c590c7e8d45e57
|
4
|
+
data.tar.gz: d0cc36d7647956efbb9f0d455d1bf7aacfebca6960aa4fe304bd98e166d9752d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48898f6530d4dfeea94dd20475bc204c1f4cbfe5c6d560565ad6ea3b33c756fa3c3e0f0cfa80a28919c5e88fc00a0bbc6e22d7a0031ca03b652bf8241d7ca651
|
7
|
+
data.tar.gz: 14af6c54d0e1d164a59e2b735518f5bfdf80eb47b33d6fdb78415a056adf8ea2747ee7ee6a16f15c905611c8263ef5e48c964db8f4d3ad68395cecf6894106ae
|
data/.gitignore
CHANGED
data/CHANGES.txt
CHANGED
data/NEWS
CHANGED
data/lib/splitclient-rb.rb
CHANGED
@@ -2,8 +2,7 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
require 'splitclient-rb/version'
|
4
4
|
|
5
|
-
require 'splitclient-rb/exceptions
|
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'
|
@@ -80,6 +79,7 @@ require 'splitclient-rb/engine/models/split'
|
|
80
79
|
require 'splitclient-rb/engine/models/label'
|
81
80
|
require 'splitclient-rb/engine/models/treatment'
|
82
81
|
require 'splitclient-rb/utilitites'
|
82
|
+
require 'splitclient-rb/validators'
|
83
83
|
|
84
84
|
# C extension
|
85
85
|
require 'murmurhash/murmurhash_mri'
|
@@ -26,7 +26,7 @@ module SplitIoClient
|
|
26
26
|
|
27
27
|
def get_splits(names)
|
28
28
|
splits = {}
|
29
|
-
split_names = names.
|
29
|
+
split_names = names.map { |name| namespace_key(".split.#{name}") }
|
30
30
|
splits.merge!(
|
31
31
|
@adapter
|
32
32
|
.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(
|
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(
|
51
|
+
route_impressions(sanitized_split_names, matching_key, bucketing_key, time, treatments_labels_change_numbers, attributes)
|
38
52
|
end
|
39
53
|
|
40
|
-
|
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[
|
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
|
-
|
63
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
83
|
-
return
|
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
|
-
|
94
|
-
|
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
|
-
|
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
|
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,
|
192
|
-
|
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
|
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
|
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
|
@@ -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],
|
@@ -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
|
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
|
4
|
+
version: 5.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: allocation_stats
|
@@ -325,8 +325,7 @@ files:
|
|
325
325
|
- lib/splitclient-rb/engine/parser/evaluator.rb
|
326
326
|
- lib/splitclient-rb/engine/parser/partition.rb
|
327
327
|
- lib/splitclient-rb/engine/parser/split_adapter.rb
|
328
|
-
- lib/splitclient-rb/exceptions
|
329
|
-
- lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb
|
328
|
+
- lib/splitclient-rb/exceptions.rb
|
330
329
|
- lib/splitclient-rb/localhost_split_factory.rb
|
331
330
|
- lib/splitclient-rb/localhost_utils.rb
|
332
331
|
- lib/splitclient-rb/managers/localhost_split_manager.rb
|
@@ -336,6 +335,7 @@ files:
|
|
336
335
|
- lib/splitclient-rb/split_factory_builder.rb
|
337
336
|
- lib/splitclient-rb/split_logger.rb
|
338
337
|
- lib/splitclient-rb/utilitites.rb
|
338
|
+
- lib/splitclient-rb/validators.rb
|
339
339
|
- lib/splitclient-rb/version.rb
|
340
340
|
- splitclient-rb.gemspec
|
341
341
|
- splitio.yml.example
|
@@ -357,9 +357,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
357
357
|
version: '0'
|
358
358
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
359
359
|
requirements:
|
360
|
-
- - "
|
360
|
+
- - ">="
|
361
361
|
- !ruby/object:Gem::Version
|
362
|
-
version:
|
362
|
+
version: '0'
|
363
363
|
requirements: []
|
364
364
|
rubyforge_project:
|
365
365
|
rubygems_version: 2.7.6
|