splitclient-rb 4.1.0 → 4.2.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.
- checksums.yaml +4 -4
- data/CHANGES.txt +8 -0
- data/NEWS +6 -0
- data/README.md +5 -18
- data/lib/splitclient-rb.rb +65 -54
- data/lib/{cache → splitclient-rb/cache}/adapters/memory_adapter.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/adapters/memory_adapters/map_adapter.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/adapters/memory_adapters/queue_adapter.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/adapters/redis_adapter.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/impressions/memory_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/impressions/redis_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/impressions_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/metrics/memory_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/metrics/redis_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/metrics_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/segments_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/repositories/splits_repository.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/senders/impressions_formatter.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/senders/impressions_sender.rb +1 -1
- data/lib/{cache → splitclient-rb/cache}/senders/metrics_sender.rb +1 -1
- data/lib/{cache → splitclient-rb/cache}/stores/sdk_blocker.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/stores/segment_store.rb +0 -0
- data/lib/{cache → splitclient-rb/cache}/stores/split_store.rb +0 -0
- data/lib/splitclient-rb/clients/localhost_split_client.rb +3 -3
- data/lib/splitclient-rb/clients/split_client.rb +28 -25
- data/lib/{engine → splitclient-rb/engine}/api/client.rb +4 -4
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +55 -0
- data/lib/{engine → splitclient-rb/engine}/api/impressions.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/api/metrics.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/api/segments.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/api/splits.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/evaluator/splitter.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/matchers/all_keys_matcher.rb +1 -1
- data/lib/{engine → splitclient-rb/engine}/matchers/between_matcher.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/matchers/combiners.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/matchers/combining_matcher.rb +10 -8
- data/lib/{engine → splitclient-rb/engine}/matchers/contains_all_matcher.rb +1 -1
- data/lib/{engine → splitclient-rb/engine}/matchers/contains_any_matcher.rb +1 -1
- data/lib/{engine → splitclient-rb/engine}/matchers/contains_matcher.rb +1 -1
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +16 -0
- data/lib/{engine → splitclient-rb/engine}/matchers/ends_with_matcher.rb +1 -1
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +21 -0
- data/lib/{engine → splitclient-rb/engine}/matchers/equal_to_matcher.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/matchers/equal_to_set_matcher.rb +1 -1
- data/lib/{engine → splitclient-rb/engine}/matchers/greater_than_or_equal_to_matcher.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/matchers/less_than_or_equal_to_matcher.rb +2 -2
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +23 -0
- data/lib/{engine → splitclient-rb/engine}/matchers/negation_matcher.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/matchers/part_of_set_matcher.rb +1 -1
- data/lib/{engine → splitclient-rb/engine}/matchers/set_matcher.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/matchers/starts_with_matcher.rb +1 -1
- data/lib/{engine → splitclient-rb/engine}/matchers/user_defined_segment_matcher.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/matchers/whitelist_matcher.rb +2 -2
- data/lib/{engine → splitclient-rb/engine}/metrics/binary_search_latency_tracker.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/metrics/metrics.rb +0 -0
- data/lib/splitclient-rb/engine/models/label.rb +7 -0
- data/lib/{engine → splitclient-rb/engine}/models/split.rb +0 -0
- data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
- data/lib/{engine → splitclient-rb/engine}/parser/condition.rb +21 -0
- data/lib/{engine/parser/split_treatment.rb → splitclient-rb/engine/parser/evaluator.rb} +29 -13
- data/lib/{engine → splitclient-rb/engine}/parser/partition.rb +0 -0
- data/lib/{engine → splitclient-rb/engine}/parser/split_adapter.rb +0 -0
- data/lib/{exceptions → splitclient-rb/exceptions}/sdk_blocker_timeout_expired_exception.rb +0 -0
- data/lib/splitclient-rb/localhost_utils.rb +1 -1
- data/lib/splitclient-rb/split_config.rb +7 -4
- data/lib/splitclient-rb/utilitites.rb +41 -0
- data/lib/splitclient-rb/version.rb +1 -1
- data/splitclient-rb.gemspec +6 -8
- metadata +76 -100
- data/lib/engine/models/label.rb +0 -13
- data/lib/engine/partitions/treatments.rb +0 -36
- data/lib/splitclient-rb_utilitites.rb +0 -39
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module FaradayMiddleware
|
5
|
+
class Gzip < Faraday::Middleware
|
6
|
+
ACCEPT_ENCODING = 'Accept-Encoding'.freeze
|
7
|
+
CONTENT_ENCODING = 'Content-Encoding'.freeze
|
8
|
+
CONTENT_LENGTH = 'Content-Length'.freeze
|
9
|
+
SUPPORTED_ENCODINGS = 'gzip,deflate'.freeze
|
10
|
+
RUBY_ENCODING = '1.9'.respond_to?(:force_encoding)
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
env[:request_headers][ACCEPT_ENCODING] ||= SUPPORTED_ENCODINGS
|
14
|
+
@app.call(env).on_complete do |response_env|
|
15
|
+
case response_env[:response_headers][CONTENT_ENCODING]
|
16
|
+
when 'gzip'
|
17
|
+
reset_body(response_env, &method(:uncompress_gzip))
|
18
|
+
when 'deflate'
|
19
|
+
reset_body(response_env, &method(:inflate))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset_body(env)
|
25
|
+
env[:body] = yield(env[:body])
|
26
|
+
env[:response_headers].delete(CONTENT_ENCODING)
|
27
|
+
env[:response_headers][CONTENT_LENGTH] = env[:body].length
|
28
|
+
end
|
29
|
+
|
30
|
+
def uncompress_gzip(body)
|
31
|
+
io = StringIO.new(body)
|
32
|
+
gzip_reader = if RUBY_ENCODING
|
33
|
+
Zlib::GzipReader.new(io, :encoding => 'ASCII-8BIT')
|
34
|
+
else
|
35
|
+
Zlib::GzipReader.new(io)
|
36
|
+
end
|
37
|
+
gzip_reader.read
|
38
|
+
end
|
39
|
+
|
40
|
+
def inflate(body)
|
41
|
+
# Inflate as a DEFLATE (RFC 1950+RFC 1951) stream
|
42
|
+
Zlib::Inflate.inflate(body)
|
43
|
+
rescue Zlib::DataError
|
44
|
+
# Fall back to inflating as a "raw" deflate stream which
|
45
|
+
# Microsoft servers return
|
46
|
+
inflate = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
47
|
+
begin
|
48
|
+
inflate.inflate(body)
|
49
|
+
ensure
|
50
|
+
inflate.close
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -29,7 +29,7 @@ module SplitIoClient
|
|
29
29
|
legacy = (legacy_algo == 1 || legacy_algo == nil) ? true : false
|
30
30
|
|
31
31
|
if partitions.empty?
|
32
|
-
return
|
32
|
+
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
33
33
|
end
|
34
34
|
|
35
35
|
if hundred_percent_one_treatment?(partitions)
|
@@ -101,7 +101,7 @@ module SplitIoClient
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
return
|
104
|
+
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
105
105
|
end
|
106
106
|
|
107
107
|
#
|
@@ -12,7 +12,7 @@ module SplitIoClient
|
|
12
12
|
@end_value = get_formatted_value attribute_hash[:end_value], true
|
13
13
|
end
|
14
14
|
|
15
|
-
def match?(
|
15
|
+
def match?(_matching_key, _bucketing_key, _evaluator, attributes)
|
16
16
|
matches = false
|
17
17
|
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
18
18
|
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
@@ -41,7 +41,7 @@ module SplitIoClient
|
|
41
41
|
return value
|
42
42
|
when "DATETIME"
|
43
43
|
value = value/1000 if is_sdk_data
|
44
|
-
return ::Utilities.to_milis_zero_out_from_seconds value
|
44
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_seconds value
|
45
45
|
else
|
46
46
|
@logger.error('Invalid data type')
|
47
47
|
end
|
File without changes
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'engine/matchers/combiners'
|
2
|
-
|
3
1
|
module SplitIoClient
|
4
2
|
#
|
5
3
|
# class to implement the combining matcher
|
@@ -31,14 +29,14 @@ module SplitIoClient
|
|
31
29
|
# @param key [string] key value to be matched
|
32
30
|
#
|
33
31
|
# @return [boolean] match value for combiner delegates
|
34
|
-
def match?(
|
32
|
+
def match?(matching_key, bucketing_key, evaluator, attributes)
|
35
33
|
if @matcher_list.empty?
|
36
34
|
return false
|
37
35
|
end
|
38
36
|
|
39
37
|
case @combiner
|
40
38
|
when Combiners::AND
|
41
|
-
return and_eval(
|
39
|
+
return and_eval(matching_key, bucketing_key, evaluator, attributes)
|
42
40
|
else
|
43
41
|
@logger.error('Invalid combiner type')
|
44
42
|
return false
|
@@ -49,14 +47,18 @@ module SplitIoClient
|
|
49
47
|
# auxiliary method to evaluate each of the matchers within the combiner
|
50
48
|
#
|
51
49
|
# @param key [string] key value to be matched
|
50
|
+
# @param evaluator [Evaluator] used in dependency_matcher
|
51
|
+
# @param attributes [hash] attributes to pass to the treatment class
|
52
52
|
#
|
53
53
|
# @return [boolean] match value for combiner delegates
|
54
|
-
def and_eval(
|
55
|
-
result = true
|
54
|
+
def and_eval(matching_key, bucketing_key, evaluator, attributes)
|
56
55
|
@matcher_list.each do |delegate|
|
57
|
-
|
56
|
+
matched = delegate.match?(matching_key, bucketing_key, evaluator, attributes)
|
57
|
+
|
58
|
+
return false unless matched
|
58
59
|
end
|
59
|
-
|
60
|
+
|
61
|
+
true
|
60
62
|
end
|
61
63
|
|
62
64
|
#
|
@@ -9,7 +9,7 @@ module SplitIoClient
|
|
9
9
|
@substr_list = substr_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(_matching_key, _bucketing_key, _evaluator, data)
|
13
13
|
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
14
|
|
15
15
|
return false if @substr_list.empty?
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class DependencyMatcher
|
3
|
+
def self.matcher_type
|
4
|
+
'IN_SPLIT_TREATMENT'.freeze
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(split, treatments)
|
8
|
+
@split = split
|
9
|
+
@treatments = treatments
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(matching_key, bucketing_key, evaluator, attributes)
|
13
|
+
@treatments.include? evaluator.call({ matching_key: matching_key, bucketing_key: bucketing_key }, @split, attributes)[:treatment]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -9,7 +9,7 @@ module SplitIoClient
|
|
9
9
|
@suffix_list = suffix_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(_matching_key, _bucketing_key, _evaluator, data)
|
13
13
|
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
14
|
|
15
15
|
return false if @suffix_list.empty?
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class EqualToBooleanMatcher
|
3
|
+
def self.matcher_type
|
4
|
+
'EQUAL_TO_BOOLEAN'.freeze
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(attribute, boolean)
|
8
|
+
@attribute = attribute
|
9
|
+
@boolean = boolean
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(_matching_key, _bucketing_key, _evaluator, data)
|
13
|
+
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
+
|
15
|
+
value = false if value.to_s.downcase == 'false'
|
16
|
+
value = true if value.to_s.downcase == 'true'
|
17
|
+
|
18
|
+
value == @boolean
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -11,7 +11,7 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(
|
14
|
+
def match?(_matching_key, _bucketing_key, _evaluator, attributes)
|
15
15
|
matches = false
|
16
16
|
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
17
17
|
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
@@ -38,7 +38,7 @@ module SplitIoClient
|
|
38
38
|
return value
|
39
39
|
when "DATETIME"
|
40
40
|
value = value/1000 if is_sdk_data
|
41
|
-
return ::Utilities.to_milis_zero_out_from_hour value
|
41
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_hour value
|
42
42
|
else
|
43
43
|
@logger.error('Invalid data type')
|
44
44
|
end
|
@@ -11,7 +11,7 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(
|
14
|
+
def match?(_matching_key, _bucketing_key, _evaluator, attributes)
|
15
15
|
matches = false
|
16
16
|
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
17
17
|
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
@@ -38,7 +38,7 @@ module SplitIoClient
|
|
38
38
|
return value
|
39
39
|
when "DATETIME"
|
40
40
|
value = value/1000 if is_sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_our
|
41
|
-
return ::Utilities.to_milis_zero_out_from_seconds value
|
41
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_seconds value
|
42
42
|
else
|
43
43
|
@logger.error('Invalid data type')
|
44
44
|
end
|
@@ -11,7 +11,7 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(
|
14
|
+
def match?(_matching_key, _bucketing_key, _evaluator, attributes)
|
15
15
|
matches = false
|
16
16
|
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
17
17
|
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
@@ -38,7 +38,7 @@ module SplitIoClient
|
|
38
38
|
return value
|
39
39
|
when "DATETIME"
|
40
40
|
value = value/1000 if is_sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_our
|
41
|
-
return ::Utilities.to_milis_zero_out_from_seconds value
|
41
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_seconds value
|
42
42
|
else
|
43
43
|
@logger.error('Invalid data type')
|
44
44
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class MatchesStringMatcher
|
3
|
+
def self.matcher_type
|
4
|
+
'MATCHES_STRING'.freeze
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(attribute, regexp_string)
|
8
|
+
@attribute = attribute
|
9
|
+
@regexp_string = regexp_string
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(_matching_key, _bucketing_key, _evaluator, data)
|
13
|
+
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
+
|
15
|
+
if @regexp_string.is_a? Regexp
|
16
|
+
(value =~ @regexp_string) != nil
|
17
|
+
else
|
18
|
+
# String here
|
19
|
+
value == @regexp_string
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -19,8 +19,8 @@ module SplitIoClient
|
|
19
19
|
# @param key [string] key value to be matched
|
20
20
|
#
|
21
21
|
# @return [boolean] evaluation of the negation matcher
|
22
|
-
def match?(
|
23
|
-
!@matcher.match?(
|
22
|
+
def match?(matching_key, bucketing_key, evaluator, attributes)
|
23
|
+
!@matcher.match?(matching_key, bucketing_key, evaluator, attributes)
|
24
24
|
end
|
25
25
|
|
26
26
|
#
|
File without changes
|
@@ -9,7 +9,7 @@ module SplitIoClient
|
|
9
9
|
@prefix_list = prefix_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(_matching_key, _bucketing_key, _evaluator, data)
|
13
13
|
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
14
|
|
15
15
|
return false if @prefix_list.empty?
|
@@ -19,8 +19,8 @@ module SplitIoClient
|
|
19
19
|
# @param key [string] key value to be matched
|
20
20
|
#
|
21
21
|
# @return [boolean] evaluation of the key against the segment
|
22
|
-
def match?(
|
23
|
-
@segments_repository.in_segment?(@segment_name,
|
22
|
+
def match?(matching_key, _bucketing_key, _evaluator, attributes)
|
23
|
+
@segments_repository.in_segment?(@segment_name, matching_key)
|
24
24
|
end
|
25
25
|
|
26
26
|
#
|
@@ -20,10 +20,10 @@ module SplitIoClient
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def match?(
|
23
|
+
def match?(matching_key, _bucketing_key, _evaluator, whitelist_data)
|
24
24
|
matches = false
|
25
25
|
if !(@matcher_type == "ATTR_WHITELIST")
|
26
|
-
matches = @whitelist.include?(
|
26
|
+
matches = @whitelist.include?(matching_key)
|
27
27
|
else
|
28
28
|
if (!whitelist_data.nil? && whitelist_data.key?(@attribute.to_sym))
|
29
29
|
value = whitelist_data[@attribute.to_sym]
|
File without changes
|
File without changes
|
File without changes
|
@@ -157,6 +157,27 @@ module SplitIoClient
|
|
157
157
|
)
|
158
158
|
end
|
159
159
|
|
160
|
+
def matcher_in_split_treatment(params)
|
161
|
+
DependencyMatcher.new(
|
162
|
+
params[:matcher][:dependencyMatcherData][:split],
|
163
|
+
params[:matcher][:dependencyMatcherData][:treatments]
|
164
|
+
)
|
165
|
+
end
|
166
|
+
|
167
|
+
def matcher_equal_to_boolean(params)
|
168
|
+
EqualToBooleanMatcher.new(
|
169
|
+
params[:matcher][:keySelector][:attribute],
|
170
|
+
params[:matcher][:booleanMatcherData]
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
def matcher_matches_string(params)
|
175
|
+
MatchesStringMatcher.new(
|
176
|
+
params[:matcher][:keySelector][:attribute],
|
177
|
+
params[:matcher][:stringMatcherData]
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
160
181
|
#
|
161
182
|
# @return [object] the negate value for this condition
|
162
183
|
def negate
|