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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13e5b4a2d803a9467000def80b168f34909b87db
4
- data.tar.gz: 2f5f6385d8bba688b501b68d63a1a0f30af063ab
3
+ metadata.gz: 0e5324edf62d055631e1ca02815169b09fc0b922
4
+ data.tar.gz: fb7d2a857376a2af0447810111929d0d1451d8d1
5
5
  SHA512:
6
- metadata.gz: 509d8611a21232b241550ebde3815aa440144bf4ae096a0182250078a0eb2d9961234dfc8515621fdbb503126794151a27d278049e1a79aea40520b188848d07
7
- data.tar.gz: da1a62bec54e13514ce31067d13f9f613a29b2ef4b6b1ba47dc38c849df89f194bd0640a063c3d19f3424efca36283cd731e56e7210fc3d3b3506ac5b1e90885
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.
@@ -17,7 +17,7 @@ module SplitIoClient
17
17
  # @param key [string] key value to be matched
18
18
  #
19
19
  # @return [boolean] true for all instances
20
- def match?(key)
20
+ def match?(key, attributes)
21
21
  true
22
22
  end
23
23
 
@@ -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
- #throws error
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 &= (delegate.match?(key))
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?(whitelist_data)
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
- # @return [object] the segment for this condition in case it has a segment matcher
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
- # @return [object] the whitelist for this condition in case it has a whitelist matcher
49
- def matcher_whitelist
50
- result = nil
51
- if self.matcher == 'WHITELIST'
52
- is_user_whitelist = ( (@data[:matcherGroup][:matchers].first[:keySelector]).nil? || (@data[:matcherGroup][:matchers].first[:keySelector])[:attribute].nil? )
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
- def matcher_equal
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
- if self.matcher == 'EQUAL_TO'
68
- attribute = (@data[:matcherGroup][:matchers].first[:keySelector])[:attribute]
69
- value = (@data[:matcherGroup][:matchers].first[:unaryNumericMatcherData])[:value]
70
- data_type = (@data[:matcherGroup][:matchers].first[:unaryNumericMatcherData])[:dataType]
71
- result = {attribute: attribute, value: value, data_type: data_type}
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 matcher_greater_than_or_equal
77
- result = nil
78
- if self.matcher == 'GREATER_THAN_OR_EQUAL_TO'
79
- attribute = (@data[:matcherGroup][:matchers].first[:keySelector])[:attribute]
80
- value = (@data[:matcherGroup][:matchers].first[:unaryNumericMatcherData])[:value]
81
- data_type = (@data[:matcherGroup][:matchers].first[:unaryNumericMatcherData])[:dataType]
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 matcher_less_than_or_equal
88
- result = nil
89
- if self.matcher == 'LESS_THAN_OR_EQUAL_TO'
90
- attribute = (@data[:matcherGroup][:matchers].first[:keySelector])[:attribute]
91
- value = (@data[:matcherGroup][:matchers].first[:unaryNumericMatcherData])[:value]
92
- data_type = (@data[:matcherGroup][:matchers].first[:unaryNumericMatcherData])[:dataType]
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 matcher_between
99
- result = nil
100
- if self.matcher == 'BETWEEN'
101
- attribute = (@data[:matcherGroup][:matchers].first[:keySelector])[:attribute]
102
- start_value = (@data[:matcherGroup][:matchers].first[:betweenMatcherData])[:start]
103
- end_value = (@data[:matcherGroup][:matchers].first[:betweenMatcherData])[:end]
104
- data_type = (@data[:matcherGroup][:matchers].first[:betweenMatcherData])[:dataType]
105
- result = {attribute: attribute, start_value: start_value, end_value: end_value, data_type: data_type}
106
- end
107
- result
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.base_uri + path) do |req|
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.base_uri + path} #{req.body}") if @config.debug_enabled
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 |c|
87
- unless c.is_empty?
88
- matcher = get_matcher_type(c)
89
- matches = attribute_matchers.include?(matcher.matcher_type) ? matcher.match?(attributes) : matcher.match?(id)
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
- result = Splitter.get_treatment(id, split.seed, c.partitions) #'true match - running split'
92
- if result.nil?
93
- return default_treatment
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(condition)
114
- final_matcher = nil
115
-
116
- case condition.matcher
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
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '1.0.3'
2
+ VERSION = '1.0.4.wip'
3
3
  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: 1.0.3
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-05-12 00:00:00.000000000 Z
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: '0'
258
+ version: 1.3.1
259
259
  requirements: []
260
260
  rubyforge_project:
261
261
  rubygems_version: 2.2.2