splitclient-rb 1.0.3 → 1.0.4.wip
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.txt +6 -0
- data/NEWS +4 -0
- data/lib/splitclient-engine/matchers/all_keys_matcher.rb +1 -1
- data/lib/splitclient-engine/matchers/between_matcher.rb +1 -1
- data/lib/splitclient-engine/matchers/combining_matcher.rb +7 -6
- data/lib/splitclient-engine/matchers/equal_to_matcher.rb +1 -1
- data/lib/splitclient-engine/matchers/greater_than_or_equal_to_matcher.rb +1 -1
- data/lib/splitclient-engine/matchers/less_than_or_equal_to_matcher.rb +1 -1
- data/lib/splitclient-engine/matchers/negation_matcher.rb +3 -3
- data/lib/splitclient-engine/matchers/user_defined_segment_matcher.rb +1 -1
- data/lib/splitclient-engine/matchers/whitelist_matcher.rb +2 -2
- data/lib/splitclient-engine/parser/condition.rb +50 -59
- data/lib/splitclient-engine/parser/split_adapter.rb +2 -2
- data/lib/splitclient-engine/parser/split_parser.rb +17 -36
- data/lib/splitclient-rb/split_config.rb +12 -0
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e5324edf62d055631e1ca02815169b09fc0b922
|
4
|
+
data.tar.gz: fb7d2a857376a2af0447810111929d0d1451d8d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0b42997a3b7ba035856ddf5ccf70e6cbdc5fc9758b54f1582609d12b11c88d93a8ccf5ff4df623588634eb53ff3a9013601275fcd881ddfd5522cc810f0c1a1
|
7
|
+
data.tar.gz: 6a2f0e5ec5b12f627165ee199d66bed3df07daf9f564b7baf8b48637da8a52e9e8e405918c013998e298ebd36d4c5ab6c840795b020aed4832a3d4aab5fe79e8
|
data/CHANGES.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
1.0.4
|
2
|
+
|
3
|
+
- added support for AND combiner on conditions
|
4
|
+
- added events_uri as config param which defines the metrics post url
|
5
|
+
- updated metrics post default endpoint to be https://events.split.io/api/
|
6
|
+
|
1
7
|
1.0.3
|
2
8
|
- fixed refresh rate intervals issue
|
3
9
|
- fixed datetime bug for split definitions created directly from api
|
data/NEWS
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
1.0.4
|
2
|
+
|
3
|
+
Added AND combiner for conditions support. Added events_uri config param which is the url where the metrics post are send to.
|
4
|
+
|
1
5
|
1.0.3
|
2
6
|
|
3
7
|
This version of the gem fixes two minor bugs related to the config option for the refresh rates, as well as an inconsistency for the split definitions that are not created from the web app, but directly from the api instead.
|
@@ -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?(attributes)
|
15
|
+
def match?(key, 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])
|
@@ -31,16 +31,17 @@ module SplitIoClient
|
|
31
31
|
# @param key [string] key value to be matched
|
32
32
|
#
|
33
33
|
# @return [boolean] match value for combiner delegates
|
34
|
-
def match?(key)
|
34
|
+
def match?(key, attributes)
|
35
35
|
if @matcher_list.empty?
|
36
36
|
return false
|
37
37
|
end
|
38
38
|
|
39
39
|
case @combiner
|
40
40
|
when Combiners::AND
|
41
|
-
return and_eval(key)
|
41
|
+
return and_eval(key, attributes)
|
42
42
|
else
|
43
|
-
|
43
|
+
@logger.error('Invalid combiner type')
|
44
|
+
return false
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
@@ -50,10 +51,10 @@ module SplitIoClient
|
|
50
51
|
# @param key [string] key value to be matched
|
51
52
|
#
|
52
53
|
# @return [boolean] match value for combiner delegates
|
53
|
-
def and_eval(key)
|
54
|
+
def and_eval(key, attributes)
|
54
55
|
result = true
|
55
56
|
@matcher_list.each do |delegate|
|
56
|
-
result &=
|
57
|
+
result &= delegate.match? key, attributes
|
57
58
|
end
|
58
59
|
result
|
59
60
|
end
|
@@ -91,4 +92,4 @@ module SplitIoClient
|
|
91
92
|
|
92
93
|
end
|
93
94
|
|
94
|
-
end
|
95
|
+
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?(attributes)
|
14
|
+
def match?(key, 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])
|
@@ -11,7 +11,7 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(attributes)
|
14
|
+
def match?(key, 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])
|
@@ -11,7 +11,7 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(attributes)
|
14
|
+
def match?(key, 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])
|
@@ -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?(key)
|
23
|
-
!@matcher.match?(key)
|
22
|
+
def match?(key, attributes)
|
23
|
+
!@matcher.match?(key, attributes)
|
24
24
|
end
|
25
25
|
|
26
26
|
#
|
@@ -51,4 +51,4 @@ module SplitIoClient
|
|
51
51
|
|
52
52
|
end
|
53
53
|
|
54
|
-
end
|
54
|
+
end
|
@@ -22,7 +22,7 @@ module SplitIoClient
|
|
22
22
|
# @param key [string] key value to be matched
|
23
23
|
#
|
24
24
|
# @return [boolean] evaluation of the key against the segment
|
25
|
-
def match?(key)
|
25
|
+
def match?(key, attributes)
|
26
26
|
matches = false
|
27
27
|
unless @segment.users.nil?
|
28
28
|
matches = @segment.users.include?(key)
|
@@ -20,10 +20,10 @@ module SplitIoClient
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def match?(whitelist_data)
|
23
|
+
def match?(key, whitelist_data)
|
24
24
|
matches = false
|
25
25
|
if !(@matcher_type == "ATTR_WHITELIST")
|
26
|
-
matches = @whitelist.include?(
|
26
|
+
matches = @whitelist.include?(key)
|
27
27
|
else
|
28
28
|
if (!whitelist_data.nil? && whitelist_data.key?(@attribute.to_sym))
|
29
29
|
value = whitelist_data[@attribute.to_sym]
|
@@ -16,6 +16,10 @@ module SplitIoClient
|
|
16
16
|
@partitions = set_partitions
|
17
17
|
end
|
18
18
|
|
19
|
+
def create_condition_matcher matchers
|
20
|
+
CombiningMatcher.new(combiner, matchers) unless combiner.nil?
|
21
|
+
end
|
22
|
+
|
19
23
|
#
|
20
24
|
# @return [object] the combiner value for this condition
|
21
25
|
def combiner
|
@@ -34,77 +38,64 @@ module SplitIoClient
|
|
34
38
|
@data[:matcherGroup][:matchers]
|
35
39
|
end
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
def matcher_segment
|
40
|
-
result = nil
|
41
|
-
if self.matcher == 'IN_SEGMENT'
|
42
|
-
result = (@data[:matcherGroup][:matchers].first[:userDefinedSegmentMatcherData])[:segmentName]
|
43
|
-
end
|
44
|
-
result
|
41
|
+
def matcher_all_keys params
|
42
|
+
AllKeysMatcher.new
|
45
43
|
end
|
46
44
|
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#is_attribute_whitelist? = !is_user_whitelist?
|
54
|
-
if is_user_whitelist
|
55
|
-
result = (@data[:matcherGroup][:matchers].first[:whitelistMatcherData])[:whitelist]
|
56
|
-
else
|
57
|
-
attribute = (@data[:matcherGroup][:matchers].first[:keySelector])[:attribute]
|
58
|
-
white_list = (@data[:matcherGroup][:matchers].first[:whitelistMatcherData])[:whitelist]
|
59
|
-
result = {attribute: attribute, value: white_list}
|
60
|
-
end
|
61
|
-
end
|
62
|
-
result
|
45
|
+
#returns UserDefinedSegmentMatcher[object]
|
46
|
+
def matcher_in_segment params
|
47
|
+
matcher = params[:matcher]
|
48
|
+
segments = params[:segments]
|
49
|
+
segment = segments.get_segment(matcher[:userDefinedSegmentMatcherData][:segmentName])
|
50
|
+
segment.is_empty? ? UserDefinedSegmentMatcher.new(nil) : UserDefinedSegmentMatcher.new(segment)
|
63
51
|
end
|
64
52
|
|
65
|
-
|
53
|
+
#returns WhitelistMatcher[object] the whitelist for this condition in case it has a whitelist matcher
|
54
|
+
def matcher_whitelist params
|
66
55
|
result = nil
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
56
|
+
matcher = params[:matcher]
|
57
|
+
is_user_whitelist = ((matcher[:keySelector]).nil? || (matcher[:keySelector])[:attribute].nil?)
|
58
|
+
if is_user_whitelist
|
59
|
+
result = (matcher[:whitelistMatcherData])[:whitelist]
|
60
|
+
else
|
61
|
+
attribute = (matcher[:keySelector])[:attribute]
|
62
|
+
white_list = (matcher[:whitelistMatcherData])[:whitelist]
|
63
|
+
result = {attribute: attribute, value: white_list}
|
72
64
|
end
|
73
|
-
result
|
65
|
+
WhitelistMatcher.new(result)
|
74
66
|
end
|
75
67
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
result = {attribute: attribute, value: value, data_type: data_type}
|
83
|
-
end
|
84
|
-
result
|
68
|
+
def matcher_equal_to params
|
69
|
+
matcher = params[:matcher]
|
70
|
+
attribute = (matcher[:keySelector])[:attribute]
|
71
|
+
value = (matcher[:unaryNumericMatcherData])[:value]
|
72
|
+
data_type = (matcher[:unaryNumericMatcherData])[:dataType]
|
73
|
+
EqualToMatcher.new({attribute: attribute, value: value, data_type: data_type})
|
85
74
|
end
|
86
75
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
result = {attribute: attribute, value: value, data_type: data_type}
|
94
|
-
end
|
95
|
-
result
|
76
|
+
def matcher_greater_than_or_equal_to params
|
77
|
+
matcher = params[:matcher]
|
78
|
+
attribute = (matcher[:keySelector])[:attribute]
|
79
|
+
value = (matcher[:unaryNumericMatcherData])[:value]
|
80
|
+
data_type = (matcher[:unaryNumericMatcherData])[:dataType]
|
81
|
+
GreaterThanOrEqualToMatcher.new({attribute: attribute, value: value, data_type: data_type})
|
96
82
|
end
|
97
83
|
|
98
|
-
def
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
84
|
+
def matcher_less_than_or_equal_to params
|
85
|
+
matcher = params[:matcher]
|
86
|
+
attribute = (matcher[:keySelector])[:attribute]
|
87
|
+
value = (matcher[:unaryNumericMatcherData])[:value]
|
88
|
+
data_type = (matcher[:unaryNumericMatcherData])[:dataType]
|
89
|
+
LessThanOrEqualToMatcher.new({attribute: attribute, value: value, data_type: data_type})
|
90
|
+
end
|
91
|
+
|
92
|
+
def matcher_between params
|
93
|
+
matcher = params[:matcher]
|
94
|
+
attribute = (matcher[:keySelector])[:attribute]
|
95
|
+
start_value = (matcher[:betweenMatcherData])[:start]
|
96
|
+
end_value = (matcher[:betweenMatcherData])[:end]
|
97
|
+
data_type = (matcher[:betweenMatcherData])[:dataType]
|
98
|
+
BetweenMatcher.new({attribute: attribute, start_value: start_value, end_value: end_value, data_type: data_type})
|
108
99
|
end
|
109
100
|
|
110
101
|
#
|
@@ -144,7 +144,7 @@ module SplitIoClient
|
|
144
144
|
#
|
145
145
|
# @return [object] response to the request
|
146
146
|
def post_api(path, param)
|
147
|
-
@api_client.post (@config.
|
147
|
+
@api_client.post (@config.events_uri + path) do |req|
|
148
148
|
req.headers['Authorization'] = 'Bearer ' + @api_key
|
149
149
|
req.headers['Content-Type'] = 'application/json'
|
150
150
|
req.headers['SplitSDKVersion'] = SplitIoClient::SplitClient.sdk_version
|
@@ -153,7 +153,7 @@ module SplitIoClient
|
|
153
153
|
req.body = param.to_json
|
154
154
|
req.options.timeout = @config.read_timeout
|
155
155
|
req.options.open_timeout = @config.connection_timeout
|
156
|
-
@config.logger.debug("POST #{@config.
|
156
|
+
@config.logger.debug("POST #{@config.events_uri + path} #{req.body}") if @config.debug_enabled
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
@@ -80,27 +80,21 @@ module SplitIoClient
|
|
80
80
|
# @return treatment [object] treatment for this user key, split pair
|
81
81
|
def get_split_treatment(id, name, default_treatment, attributes = nil)
|
82
82
|
split = get_split(name)
|
83
|
-
attribute_matchers = ["ATTR_WHITELIST", "EQUAL_TO", "GREATER_THAN_OR_EQUAL_TO", "LESS_THAN_OR_EQUAL_TO", "BETWEEN"]
|
84
|
-
|
85
83
|
if !split.is_empty? && split.status == 'ACTIVE' && !split.killed?
|
86
|
-
split.conditions.each do |
|
87
|
-
unless
|
88
|
-
matcher = get_matcher_type
|
89
|
-
matches =
|
84
|
+
split.conditions.each do |condit|
|
85
|
+
unless condit.is_empty?
|
86
|
+
matcher = get_matcher_type condit
|
87
|
+
matches = matcher.match? id, attributes
|
90
88
|
if matches
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
else
|
95
|
-
return result
|
96
|
-
end
|
89
|
+
treatment = Splitter.get_treatment id, split.seed, condit.partitions
|
90
|
+
result = treatment.nil? ? default_treatment : treatment
|
91
|
+
return result
|
97
92
|
end
|
98
93
|
end
|
99
94
|
end
|
100
95
|
elsif !split.is_empty? && split.status == 'ARCHIVED'
|
101
96
|
return Treatments::CONTROL
|
102
97
|
end
|
103
|
-
|
104
98
|
default_treatment
|
105
99
|
end
|
106
100
|
|
@@ -110,32 +104,19 @@ module SplitIoClient
|
|
110
104
|
# @param contidion [object] a condition object
|
111
105
|
#
|
112
106
|
# @return matcher [object] the matcher object for the given condition
|
113
|
-
def get_matcher_type(
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
when 'ALL_KEYS'
|
118
|
-
final_matcher = AllKeysMatcher.new
|
119
|
-
when 'IN_SEGMENT'
|
120
|
-
segment = @segments.get_segment(condition.matcher_segment)
|
121
|
-
final_matcher = segment.is_empty? ? UserDefinedSegmentMatcher.new(nil) : UserDefinedSegmentMatcher.new(segment)
|
122
|
-
when 'WHITELIST'
|
123
|
-
final_matcher = WhitelistMatcher.new(condition.matcher_whitelist)
|
124
|
-
when 'EQUAL_TO'
|
125
|
-
final_matcher = EqualToMatcher.new(condition.matcher_equal)
|
126
|
-
when 'GREATER_THAN_OR_EQUAL_TO'
|
127
|
-
final_matcher = GreaterThanOrEqualToMatcher.new(condition.matcher_greater_than_or_equal)
|
128
|
-
when 'LESS_THAN_OR_EQUAL_TO'
|
129
|
-
final_matcher = LessThanOrEqualToMatcher.new(condition.matcher_less_than_or_equal)
|
130
|
-
when 'BETWEEN'
|
131
|
-
final_matcher = BetweenMatcher.new(condition.matcher_between)
|
132
|
-
else
|
133
|
-
@logger.error('Invalid matcher type')
|
107
|
+
def get_matcher_type(condit)
|
108
|
+
matchers = []
|
109
|
+
condit.matchers.each do |matcher|
|
110
|
+
matchers << condit.send("matcher_#{matcher[:matcherType].downcase}", {matcher: matcher, segments: @segments})
|
134
111
|
end
|
112
|
+
final_matcher = condit.create_condition_matcher matchers
|
135
113
|
|
136
|
-
final_matcher
|
114
|
+
if final_matcher.nil?
|
115
|
+
@logger.error('Invalid matcher type')
|
116
|
+
else
|
117
|
+
final_matcher
|
118
|
+
end
|
137
119
|
end
|
138
|
-
|
139
120
|
end
|
140
121
|
|
141
122
|
end
|
@@ -12,6 +12,7 @@ module SplitIoClient
|
|
12
12
|
#
|
13
13
|
# @param opts [Hash] optional hash with configuration options
|
14
14
|
# @option opts [String] :base_uri ("https://sdk.split.io/api/") The base URL for split API end points
|
15
|
+
# @option opts [String] :events_uri ("https://events.split.io/api/") The events URL for events end points
|
15
16
|
# @option opts [Int] :read_timeout (10) The read timeout for network connections in seconds.
|
16
17
|
# @option opts [Int] :connection_timeout (2) The connect timeout for network connections in seconds.
|
17
18
|
# @option opts [Object] :local_store A cache store for the Faraday HTTP caching library. Defaults to the Rails cache in a Rails environment, or a thread-safe in-memory store otherwise.
|
@@ -25,6 +26,7 @@ module SplitIoClient
|
|
25
26
|
# @return [type] SplitConfig with configuration options
|
26
27
|
def initialize(opts = {})
|
27
28
|
@base_uri = (opts[:base_uri] || SplitConfig.default_base_uri).chomp('/')
|
29
|
+
@events_uri = (opts[:events_uri] || SplitConfig.default_events_uri).chomp('/')
|
28
30
|
@local_store = opts[:local_store] || SplitConfig.default_local_store
|
29
31
|
@connection_timeout = opts[:connection_timeout] || SplitConfig.default_connection_timeout
|
30
32
|
@read_timeout = opts[:read_timeout] || SplitConfig.default_read_timeout
|
@@ -44,6 +46,12 @@ module SplitIoClient
|
|
44
46
|
# @return [String] The configured base URL for the split API end points
|
45
47
|
attr_reader :base_uri
|
46
48
|
|
49
|
+
#
|
50
|
+
# The base URL for split events API end points
|
51
|
+
#
|
52
|
+
# @return [String] The configured URL for the events API end points
|
53
|
+
attr_reader :events_uri
|
54
|
+
|
47
55
|
#
|
48
56
|
# The store for the Faraday HTTP caching library. Stores should respond to
|
49
57
|
# 'read', 'write' and 'delete' requests.
|
@@ -100,6 +108,10 @@ module SplitIoClient
|
|
100
108
|
'https://sdk.split.io/api/'
|
101
109
|
end
|
102
110
|
|
111
|
+
def self.default_events_uri
|
112
|
+
'https://events.split.io/api/'
|
113
|
+
end
|
114
|
+
|
103
115
|
# @return [LocalStore] configuration value for local cache store
|
104
116
|
def self.default_local_store
|
105
117
|
defined?(Rails) && Rails.respond_to?(:cache) ? Rails.cache : LocalStore.new
|
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: 1.0.
|
4
|
+
version: 1.0.4.wip
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -253,9 +253,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
253
253
|
version: '0'
|
254
254
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
255
255
|
requirements:
|
256
|
-
- - "
|
256
|
+
- - ">"
|
257
257
|
- !ruby/object:Gem::Version
|
258
|
-
version:
|
258
|
+
version: 1.3.1
|
259
259
|
requirements: []
|
260
260
|
rubyforge_project:
|
261
261
|
rubygems_version: 2.2.2
|