splitclient-rb 6.0.1 → 6.1.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -1
- data/.simplecov +1 -0
- data/README.md +2 -2
- data/lib/splitclient-rb.rb +1 -0
- data/lib/splitclient-rb/clients/split_client.rb +30 -9
- data/lib/splitclient-rb/engine/api/client.rb +8 -9
- data/lib/splitclient-rb/engine/api/events.rb +4 -2
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +10 -8
- data/lib/splitclient-rb/engine/api/impressions.rb +4 -2
- data/lib/splitclient-rb/engine/api/metrics.rb +5 -5
- data/lib/splitclient-rb/engine/api/segments.rb +5 -1
- data/lib/splitclient-rb/engine/api/splits.rb +4 -4
- data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +8 -13
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +12 -23
- data/lib/splitclient-rb/engine/matchers/combiners.rb +3 -1
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +16 -24
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +10 -7
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +7 -6
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +19 -8
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +8 -3
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +21 -6
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +17 -8
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +11 -23
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +7 -6
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +13 -25
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +13 -25
- data/lib/splitclient-rb/engine/matchers/matcher.rb +30 -0
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +6 -2
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +8 -22
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +10 -7
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +7 -1
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +18 -5
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +7 -25
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +33 -35
- data/lib/splitclient-rb/managers/split_manager.rb +10 -3
- data/lib/splitclient-rb/split_config.rb +34 -9
- data/lib/splitclient-rb/split_factory.rb +27 -0
- data/lib/splitclient-rb/validators.rb +104 -36
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +6 -4
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
#
|
3
5
|
# class to implement the combining matcher
|
4
6
|
#
|
5
|
-
class CombiningMatcher
|
6
|
-
MATCHER_TYPE = 'COMBINING_MATCHER'
|
7
|
+
class CombiningMatcher < Matcher
|
8
|
+
MATCHER_TYPE = 'COMBINING_MATCHER'
|
7
9
|
|
8
10
|
def initialize(combiner = '', matchers = [])
|
9
11
|
@combiner = combiner
|
@@ -20,12 +22,18 @@ module SplitIoClient
|
|
20
22
|
#
|
21
23
|
# @return [boolean]
|
22
24
|
def match?(args)
|
23
|
-
|
25
|
+
if @matchers.empty?
|
26
|
+
SplitLogger.log_if_debug('[CombiningMatcher] Matchers Empty')
|
27
|
+
return false
|
28
|
+
end
|
24
29
|
|
25
30
|
case @combiner
|
26
31
|
when Combiners::AND
|
27
|
-
|
32
|
+
matches = eval_and(args)
|
33
|
+
SplitLogger.log_if_debug("[CombiningMatcher] Combiner AND result -> #{matches}")
|
34
|
+
return matches
|
28
35
|
else
|
36
|
+
SplitLogger.log_if_debug("[CombiningMatcher] Invalid Combiner Type - Combiner -> #{@combiner}")
|
29
37
|
@logger.error('Invalid combiner type')
|
30
38
|
end
|
31
39
|
|
@@ -43,7 +51,9 @@ module SplitIoClient
|
|
43
51
|
# @return [boolean] match value for combiner delegates
|
44
52
|
def eval_and(args)
|
45
53
|
# Convert all keys to symbols
|
46
|
-
|
54
|
+
if args && args[:attributes]
|
55
|
+
args[:attributes] = args[:attributes].each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
|
56
|
+
end
|
47
57
|
@matchers.all? do |matcher|
|
48
58
|
if match_with_key?(matcher)
|
49
59
|
matcher.match?(value: args[:matching_key])
|
@@ -57,28 +67,10 @@ module SplitIoClient
|
|
57
67
|
matcher.respond_to?(:attribute) && matcher.attribute.nil? && matcher.string_type?
|
58
68
|
end
|
59
69
|
|
60
|
-
#
|
61
|
-
# evaluates if the given object equals the matcher
|
62
|
-
#
|
63
|
-
# @param obj [object] object to be evaluated
|
64
|
-
#
|
65
|
-
# @returns [boolean] true if obj equals the matcher
|
66
|
-
def equals?(obj)
|
67
|
-
if obj.nil?
|
68
|
-
false
|
69
|
-
elsif !obj.instance_of?(CombiningMatcher)
|
70
|
-
false
|
71
|
-
elsif self.equal?(obj)
|
72
|
-
true
|
73
|
-
else
|
74
|
-
false
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
70
|
#
|
79
71
|
# function to print string value for this matcher
|
80
72
|
#
|
81
|
-
# @
|
73
|
+
# @return [string] string value of this matcher
|
82
74
|
def to_s
|
83
75
|
@matcher_list.map(&:to_s).join("#{@combiner} ")
|
84
76
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class ContainsAllMatcher < SetMatcher
|
3
|
-
MATCHER_TYPE = 'CONTAINS_ALL'
|
5
|
+
MATCHER_TYPE = 'CONTAINS_ALL'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -9,13 +11,14 @@ module SplitIoClient
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def match?(args)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
if @remote_set.empty?
|
15
|
+
SplitLogger.log_if_debug('[ContainsAllMatcher] Remote Set Empty')
|
16
|
+
return false
|
17
|
+
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
matches = @remote_set.subset? local_set(args[:attributes], @attribute)
|
20
|
+
SplitLogger.log_if_debug("[ContainsAllMatcher] Remote Set #{@remote_set} contains #{@attribute} -> #{matches}")
|
21
|
+
matches
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class ContainsAnyMatcher < SetMatcher
|
3
|
-
MATCHER_TYPE = 'CONTAINS_ANY'
|
5
|
+
MATCHER_TYPE = 'CONTAINS_ANY'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -9,11 +11,10 @@ module SplitIoClient
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def match?(args)
|
12
|
-
local_set(args[:attributes], @attribute).intersect? @remote_set
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
false
|
14
|
+
matches = local_set(args[:attributes], @attribute).intersect? @remote_set
|
15
|
+
SplitLogger.log_if_debug("[ContainsAnyMatcher] Remote Set #{@remote_set} contains any \
|
16
|
+
#{@attribute} or #{args[:attributes]}-> #{matches}")
|
17
|
+
matches
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class ContainsMatcher
|
3
|
-
MATCHER_TYPE = 'CONTAINS_WITH'
|
5
|
+
MATCHER_TYPE = 'CONTAINS_WITH'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -10,21 +12,30 @@ module SplitIoClient
|
|
10
12
|
end
|
11
13
|
|
12
14
|
def match?(args)
|
13
|
-
|
14
|
-
return false if args.key?(:value) && args[:value].nil?
|
15
|
-
return false if args.key?(:attributes) && args[:attributes].nil?
|
15
|
+
SplitLogger.log_if_debug('[ContainsMatcher] evaluating value and attributes.')
|
16
16
|
|
17
|
-
|
18
|
-
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
19
|
-
end
|
17
|
+
return false unless SplitIoClient::Validators.valid_matcher_arguments(args)
|
20
18
|
|
19
|
+
value = get_value(args)
|
20
|
+
|
21
|
+
SplitLogger.log_if_debug("[ContainsMatcher] Value from parameters: #{value}.")
|
21
22
|
return false if @substr_list.empty?
|
22
23
|
|
23
|
-
@substr_list.any? { |substr| value.to_s.include? substr }
|
24
|
+
matches = @substr_list.any? { |substr| value.to_s.include? substr }
|
25
|
+
SplitLogger.log_if_debug("[ContainsMatcher] #{@value} contains any of #{@substr_list} -> #{matches} .")
|
26
|
+
matches
|
24
27
|
end
|
25
28
|
|
26
29
|
def string_type?
|
27
30
|
true
|
28
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def get_value(args)
|
36
|
+
args[:value] || args[:attributes].fetch(@attribute) do |a|
|
37
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
38
|
+
end
|
39
|
+
end
|
29
40
|
end
|
30
41
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class DependencyMatcher
|
3
|
-
MATCHER_TYPE = 'IN_SPLIT_TREATMENT'
|
5
|
+
MATCHER_TYPE = 'IN_SPLIT_TREATMENT'
|
4
6
|
|
5
7
|
def initialize(split, treatments)
|
6
8
|
@split = split
|
@@ -9,8 +11,11 @@ module SplitIoClient
|
|
9
11
|
|
10
12
|
def match?(args)
|
11
13
|
keys = { matching_key: args[:matching_key], bucketing_key: args[:bucketing_key] }
|
12
|
-
|
13
|
-
@treatments.include?(
|
14
|
+
evaluate = args[:evaluator].call(keys, @split, args[:attributes])
|
15
|
+
matches = @treatments.include?(evaluate[:treatment])
|
16
|
+
SplitLogger.log_if_debug("[dependencyMatcher] Parent split #{@split} evaluated to #{evaluate[:treatment]} \
|
17
|
+
with label #{evaluate[:label]}. #{@split} evaluated treatment is part of [#{@treatments}] ? #{matches}.")
|
18
|
+
matches
|
14
19
|
end
|
15
20
|
|
16
21
|
def string_type?
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class EndsWithMatcher
|
3
|
-
MATCHER_TYPE = 'ENDS_WITH'
|
5
|
+
MATCHER_TYPE = 'ENDS_WITH'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -10,17 +12,30 @@ module SplitIoClient
|
|
10
12
|
end
|
11
13
|
|
12
14
|
def match?(args)
|
13
|
-
value = args
|
14
|
-
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
-
end
|
15
|
+
value = get_value(args)
|
16
16
|
|
17
|
-
|
17
|
+
SplitLogger.log_if_debug("[EndsWithMatcher] Value from parameters: #{value}.")
|
18
|
+
|
19
|
+
if @suffix_list.empty?
|
20
|
+
SplitLogger.log_if_debug('[EndsWithMatcher] Sufix List empty.')
|
21
|
+
return false
|
22
|
+
end
|
18
23
|
|
19
|
-
@suffix_list.any? { |suffix| value.to_s.end_with? suffix }
|
24
|
+
matches = @suffix_list.any? { |suffix| value.to_s.end_with? suffix }
|
25
|
+
SplitLogger.log_if_debug("[EndsWithMatcher] #{value} ends with any #{@suffix_list}")
|
26
|
+
matches
|
20
27
|
end
|
21
28
|
|
22
29
|
def string_type?
|
23
30
|
true
|
24
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def get_value(args)
|
36
|
+
args[:value] || args[:attributes].fetch(@attribute) do |a|
|
37
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
38
|
+
end
|
39
|
+
end
|
25
40
|
end
|
26
41
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class EqualToBooleanMatcher
|
3
|
-
MATCHER_TYPE = 'EQUAL_TO_BOOLEAN'
|
5
|
+
MATCHER_TYPE = 'EQUAL_TO_BOOLEAN'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -10,18 +12,25 @@ module SplitIoClient
|
|
10
12
|
end
|
11
13
|
|
12
14
|
def match?(args)
|
13
|
-
value = args
|
14
|
-
|
15
|
-
|
15
|
+
value = get_value(args)
|
16
|
+
value = false if value.to_s.casecmp('false').zero?
|
17
|
+
value = true if value.to_s.casecmp('true').zero?
|
16
18
|
|
17
|
-
|
18
|
-
value
|
19
|
-
|
20
|
-
value == @boolean
|
19
|
+
matches = value == @boolean
|
20
|
+
SplitLogger.log_if_debug("[EqualToBooleanMatcher] #{value} equals to #{@boolean} -> #{matches}")
|
21
|
+
matches
|
21
22
|
end
|
22
23
|
|
23
24
|
def string_type?
|
24
25
|
false
|
25
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def get_value(args)
|
31
|
+
args[:attributes].fetch(@attribute) do |a|
|
32
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
33
|
+
end
|
34
|
+
end
|
26
35
|
end
|
27
36
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
|
-
class EqualToMatcher
|
3
|
-
MATCHER_TYPE = 'EQUAL_TO'
|
4
|
+
class EqualToMatcher < Matcher
|
5
|
+
MATCHER_TYPE = 'EQUAL_TO'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -11,29 +13,15 @@ module SplitIoClient
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def match?(args)
|
14
|
-
|
15
|
-
return false if args.key?(:value) && args[:value].nil?
|
16
|
-
return false if args.key?(:attributes) && args[:attributes].nil?
|
17
|
-
|
18
|
-
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
16
|
+
SplitLogger.log_if_debug('[EqualsToMatcher] evaluating value and attributes.')
|
19
17
|
|
20
|
-
|
21
|
-
end
|
18
|
+
return false unless SplitIoClient::Validators.valid_matcher_arguments(args)
|
22
19
|
|
23
|
-
|
24
|
-
if obj.nil?
|
25
|
-
false
|
26
|
-
elsif !obj.instance_of?(EqualToMatcher)
|
27
|
-
false
|
28
|
-
elsif self.equal?(obj)
|
29
|
-
true
|
30
|
-
else
|
31
|
-
false
|
32
|
-
end
|
33
|
-
end
|
20
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
34
21
|
|
35
|
-
|
36
|
-
|
22
|
+
matches = value.is_a?(Integer) ? (value == @value) : false
|
23
|
+
SplitLogger.log_if_debug("[EqualsToMatcher] #{value} equals to #{@value} -> #{matches}")
|
24
|
+
matches
|
37
25
|
end
|
38
26
|
|
39
27
|
private
|
@@ -43,7 +31,7 @@ module SplitIoClient
|
|
43
31
|
when 'NUMBER'
|
44
32
|
value
|
45
33
|
when 'DATETIME'
|
46
|
-
value
|
34
|
+
value /= 1000 if sdk_data
|
47
35
|
|
48
36
|
SplitIoClient::Utilities.to_milis_zero_out_from_hour value
|
49
37
|
else
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class EqualToSetMatcher < SetMatcher
|
3
|
-
MATCHER_TYPE = 'EQUAL_TO_SET'
|
5
|
+
MATCHER_TYPE = 'EQUAL_TO_SET'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -9,11 +11,10 @@ module SplitIoClient
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def match?(args)
|
12
|
-
local_set(args[:attributes], @attribute)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
false
|
14
|
+
set = local_set(args[:attributes], @attribute)
|
15
|
+
matches = set == @remote_set
|
16
|
+
SplitLogger.log_if_debug("[EqualsToSetMatcher] #{set} equals to #{@remote_set} -> #{matches}")
|
17
|
+
matches
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
|
-
class GreaterThanOrEqualToMatcher
|
3
|
-
MATCHER_TYPE = 'GREATER_THAN_OR_EQUAL_TO'
|
4
|
+
class GreaterThanOrEqualToMatcher < Matcher
|
5
|
+
MATCHER_TYPE = 'GREATER_THAN_OR_EQUAL_TO'
|
4
6
|
|
5
7
|
attr_reader :attribute
|
6
8
|
|
@@ -11,29 +13,15 @@ module SplitIoClient
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def match?(args)
|
14
|
-
|
15
|
-
return false if args.key?(:value) && args[:value].nil?
|
16
|
-
return false if args.key?(:attributes) && args[:attributes].nil?
|
17
|
-
|
18
|
-
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
16
|
+
SplitLogger.log_if_debug('[GreaterThanOrEqualToMatcher] evaluating value and attributes.')
|
19
17
|
|
20
|
-
|
21
|
-
end
|
18
|
+
return false unless SplitIoClient::Validators.valid_matcher_arguments(args)
|
22
19
|
|
23
|
-
|
24
|
-
if obj.nil?
|
25
|
-
false
|
26
|
-
elsif !obj.instance_of?(GreaterThanOrEqualToMatcher)
|
27
|
-
false
|
28
|
-
elsif self.equal?(obj)
|
29
|
-
true
|
30
|
-
else
|
31
|
-
false
|
32
|
-
end
|
33
|
-
end
|
20
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
34
21
|
|
35
|
-
|
36
|
-
|
22
|
+
matches = value.is_a?(Integer) ? (value >= @value) : false
|
23
|
+
SplitLogger.log_if_debug("[GreaterThanOrEqualToMatcher] #{value} greater than or equal to #{@value} -> #{matches}")
|
24
|
+
matches
|
37
25
|
end
|
38
26
|
|
39
27
|
private
|
@@ -41,10 +29,10 @@ module SplitIoClient
|
|
41
29
|
def formatted_value(value, sdk_data = false)
|
42
30
|
case @data_type
|
43
31
|
when 'NUMBER'
|
44
|
-
|
32
|
+
value
|
45
33
|
when 'DATETIME'
|
46
|
-
value
|
47
|
-
|
34
|
+
value /= 1000 if sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_hour
|
35
|
+
SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
|
48
36
|
else
|
49
37
|
@logger.error('Invalid data type')
|
50
38
|
end
|