splitclient-rb 4.2.2 → 4.3.0.canary.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.txt +9 -0
- data/Detailed-README.md +21 -0
- data/NEWS +5 -0
- data/exe/splitio +6 -2
- data/lib/splitclient-rb.rb +3 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +4 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +5 -0
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +6 -0
- data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +6 -0
- data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +6 -0
- data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +1 -1
- data/lib/splitclient-rb/cache/repositories/repository.rb +1 -1
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +4 -0
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +4 -0
- data/lib/splitclient-rb/cache/routers/impression_router.rb +52 -0
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +10 -4
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +1 -1
- data/lib/splitclient-rb/cache/stores/segment_store.rb +1 -1
- data/lib/splitclient-rb/cache/stores/split_store.rb +1 -1
- data/lib/splitclient-rb/clients/split_client.rb +55 -8
- data/lib/splitclient-rb/engine/matchers/attribute_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +3 -3
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +1 -3
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +1 -3
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +1 -3
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +3 -3
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +3 -3
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +3 -3
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +1 -3
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +1 -3
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +5 -8
- data/lib/splitclient-rb/engine/parser/evaluator.rb +9 -1
- data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +4 -0
- data/lib/splitclient-rb/split_config.rb +15 -1
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7aba740fb6e199e7e82a1fc59c2af161010a3028
|
4
|
+
data.tar.gz: 85b1a7476a4ed1739e9b9de1c10ebb3f641eb6ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9367028653a703dc2ae91d8dd87f6eefd1ada85c523e2fc09c9d00091ba7412a6a6449b5a5d23bdb9ea1464f16ec1f9f5d3410686c4c7ff09eb177002e81f886
|
7
|
+
data.tar.gz: 1816f164bd047b30ec7825ef8bcc5619d8ce975ef79e03622fe611fb42c06810227e8fc98df3023c421c1cf666e029cc5a185a6722d187bab3e1d4c2553154a0
|
data/CHANGES.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
4.3.0 (Sept 14th, 2017)
|
2
|
+
- Add impression listener
|
3
|
+
- Add support for client shutdown (destroy())
|
4
|
+
- Add "time" to the routed impressions
|
5
|
+
- Add support to apply attribute matcher to the traffic type
|
6
|
+
|
7
|
+
4.2.3 (August 4, 2017)
|
8
|
+
- Use ENV vars in producer
|
9
|
+
|
1
10
|
4.2.2 (July 28, 2017)
|
2
11
|
- Fix treatments array in SplitManager
|
3
12
|
|
data/Detailed-README.md
CHANGED
@@ -364,6 +364,27 @@ debug_enabled: true, # used for more verbose logging, including more debug infor
|
|
364
364
|
transport_debug_enabled: true # used for log transport data (mostly http requests, false is the default)
|
365
365
|
```
|
366
366
|
|
367
|
+
### Impression Listener
|
368
|
+
|
369
|
+
In order to capture every single impression in your app SDK provides option called Impression Listener. It works pretty straightforward: you define a class which must have instance method called `log`, which must receive 1 argument `impression`. Let's say you have the following impression listener class:
|
370
|
+
|
371
|
+
```ruby
|
372
|
+
class MyImpressionListener
|
373
|
+
def log(impression)
|
374
|
+
Logger.new($stdout).info(impression)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
```
|
378
|
+
|
379
|
+
Nothing fancy here, it just takes impression and logs it to the stdout. Now, to actually use this class you'll need to specify it in your config (i.e. initializer) like this:
|
380
|
+
|
381
|
+
```ruby
|
382
|
+
{
|
383
|
+
# other options
|
384
|
+
impression_listener: MyImpressionListener.new # do remember to initialize your class here
|
385
|
+
}
|
386
|
+
```
|
387
|
+
|
367
388
|
### SDK Modes
|
368
389
|
|
369
390
|
By default SDK would run alongside with your application and will be run in `standalone` mode, which includes two modes:
|
data/NEWS
CHANGED
data/exe/splitio
CHANGED
@@ -7,7 +7,7 @@ require 'optparse'
|
|
7
7
|
require 'yaml'
|
8
8
|
require_relative '../lib/splitclient-rb'
|
9
9
|
|
10
|
-
ARGV << '-h' if ARGV.empty?
|
10
|
+
# ARGV << '-h' if ARGV.empty?
|
11
11
|
|
12
12
|
config_path = ''
|
13
13
|
options = {}
|
@@ -84,9 +84,13 @@ begin
|
|
84
84
|
exit(1)
|
85
85
|
end
|
86
86
|
|
87
|
-
config = YAML.load_file(config_path)
|
87
|
+
config = config_path != '' ? YAML.load_file(config_path) : {}
|
88
88
|
config
|
89
89
|
.merge!(mode: :producer, cache_adapter: :redis)
|
90
90
|
.merge!(options)
|
91
|
+
.merge!(api_key: ENV['API_KEY'] || config[:api_key])
|
92
|
+
.merge!(base_uri: ENV['SDK_URI'] || config[:base_uri])
|
93
|
+
.merge!(events_uri: ENV['EVENTS_URI'] || config[:events_uri])
|
94
|
+
# IDENTIFY_BASE_URI
|
91
95
|
|
92
96
|
SplitIoClient::SplitFactory.new(config[:api_key], config)
|
data/lib/splitclient-rb.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'splitclient-rb/version'
|
2
2
|
|
3
|
+
require 'splitclient-rb/exceptions/impressions_shutdown_exception'
|
3
4
|
require 'splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception'
|
5
|
+
require 'splitclient-rb/cache/routers/impression_router'
|
4
6
|
require 'splitclient-rb/cache/adapters/memory_adapters/map_adapter'
|
5
7
|
require 'splitclient-rb/cache/adapters/memory_adapters/queue_adapter'
|
6
8
|
require 'splitclient-rb/cache/adapters/memory_adapter'
|
@@ -41,6 +43,7 @@ require 'splitclient-rb/engine/parser/condition'
|
|
41
43
|
require 'splitclient-rb/engine/parser/partition'
|
42
44
|
require 'splitclient-rb/engine/parser/split_adapter'
|
43
45
|
require 'splitclient-rb/engine/parser/evaluator'
|
46
|
+
require 'splitclient-rb/engine/matchers/attribute_matcher'
|
44
47
|
require 'splitclient-rb/engine/matchers/combiners'
|
45
48
|
require 'splitclient-rb/engine/matchers/combining_matcher'
|
46
49
|
require 'splitclient-rb/engine/matchers/all_keys_matcher'
|
@@ -10,6 +10,11 @@ module SplitIoClient
|
|
10
10
|
@current_size = Concurrent::AtomicFixnum.new(0)
|
11
11
|
end
|
12
12
|
|
13
|
+
def clear(_ = nil)
|
14
|
+
@queue = Queue.new
|
15
|
+
@current_size.value = 0
|
16
|
+
end
|
17
|
+
|
13
18
|
# Adds data to queue in non-blocking mode
|
14
19
|
def add_to_queue(data)
|
15
20
|
fail ThreadError if @current_size.value >= @max_size
|
@@ -5,7 +5,7 @@ module SplitIoClient
|
|
5
5
|
class MetricsRepository < Repository
|
6
6
|
extend Forwardable
|
7
7
|
def_delegators :@adapter, :add_count, :add_latency, :add_gauge, :counts, :latencies, :gauges,
|
8
|
-
:clear_counts, :clear_latencies, :clear_gauges
|
8
|
+
:clear_counts, :clear_latencies, :clear_gauges, :clear
|
9
9
|
|
10
10
|
def initialize(adapter, config)
|
11
11
|
@config = config
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class ImpressionRouter
|
3
|
+
attr_reader :router_thread
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
@listener = config.impression_listener
|
8
|
+
@queue = Queue.new
|
9
|
+
router_thread
|
10
|
+
|
11
|
+
if defined?(PhusionPassenger)
|
12
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
13
|
+
router_thread if forked
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(impression)
|
19
|
+
@queue.push(impression)
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_bulk(impressions)
|
23
|
+
impressions[:split_names].each do |split_name|
|
24
|
+
@queue.push(
|
25
|
+
split_name: split_name.to_s,
|
26
|
+
matching_key: impressions[:matching_key],
|
27
|
+
bucketing_key: impressions[:bucketing_key],
|
28
|
+
treatment: {
|
29
|
+
label: impressions[:treatments_labels_change_numbers][split_name.to_sym][:label],
|
30
|
+
treatment: impressions[:treatments_labels_change_numbers][split_name.to_sym][:treatment],
|
31
|
+
change_number: impressions[:treatments_labels_change_numbers][split_name.to_sym][:change_number]
|
32
|
+
},
|
33
|
+
attributes: impressions[:attributes]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def router_thread
|
41
|
+
@config.threads[:impression_router] = Thread.new do
|
42
|
+
loop do
|
43
|
+
begin
|
44
|
+
@listener.log(@queue.pop)
|
45
|
+
rescue StandardError => error
|
46
|
+
@config.log_found_exception(__method__.to_s, error)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -31,13 +31,19 @@ module SplitIoClient
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def impressions_thread
|
34
|
-
Thread.new do
|
35
|
-
|
34
|
+
@config.threads[:impressions_sender] = Thread.new do
|
35
|
+
begin
|
36
|
+
@config.logger.info('Starting impressions service')
|
36
37
|
|
37
|
-
|
38
|
+
loop do
|
39
|
+
post_impressions
|
40
|
+
|
41
|
+
sleep(SplitIoClient::Utilities.randomize_interval(@config.impressions_refresh_rate))
|
42
|
+
end
|
43
|
+
rescue SplitIoClient::ImpressionShutdownException
|
38
44
|
post_impressions
|
39
45
|
|
40
|
-
|
46
|
+
@impressions_repository.clear
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
@@ -29,7 +29,7 @@ module SplitIoClient
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def segments_thread
|
32
|
-
@sdk_blocker.segments_thread = Thread.new do
|
32
|
+
@config.threads[:segment_store] = @sdk_blocker.segments_thread = Thread.new do
|
33
33
|
@config.logger.info('Starting segments fetcher service')
|
34
34
|
@config.block_until_ready > 0 ? blocked_store : unblocked_store
|
35
35
|
end
|
@@ -29,7 +29,7 @@ module SplitIoClient
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def splits_thread
|
32
|
-
@sdk_blocker.splits_thread = Thread.new do
|
32
|
+
@config.threads[:split_store] = @sdk_blocker.splits_thread = Thread.new do
|
33
33
|
@config.logger.info('Starting splits fetcher service')
|
34
34
|
loop do
|
35
35
|
store_splits
|
@@ -27,9 +27,12 @@ module SplitIoClient
|
|
27
27
|
end
|
28
28
|
|
29
29
|
if @config.impressions_queue_size > 0
|
30
|
+
time = (Time.now.to_f * 1000.0).to_i
|
30
31
|
@impressions_repository.add_bulk(
|
31
|
-
matching_key, bucketing_key, treatments_labels_change_numbers,
|
32
|
+
matching_key, bucketing_key, treatments_labels_change_numbers, time
|
32
33
|
)
|
34
|
+
|
35
|
+
route_impressions(split_names, matching_key, bucketing_key, time, treatments_labels_change_numbers, attributes)
|
33
36
|
end
|
34
37
|
|
35
38
|
split_names = treatments_labels_change_numbers.keys
|
@@ -87,8 +90,8 @@ module SplitIoClient
|
|
87
90
|
|
88
91
|
store_impression(
|
89
92
|
split_name, matching_key, bucketing_key,
|
90
|
-
{ treatment: SplitIoClient::Engine::Models::Treatment::CONTROL, label: Engine::Models::Label::EXCEPTION },
|
91
|
-
store_impressions
|
93
|
+
{ treatment: SplitIoClient::Engine::Models::Treatment::CONTROL, label: SplitIoClient::Engine::Models::Label::EXCEPTION },
|
94
|
+
store_impressions, attributes
|
92
95
|
)
|
93
96
|
|
94
97
|
return parsed_treatment(multiple, treatment_data)
|
@@ -97,7 +100,7 @@ module SplitIoClient
|
|
97
100
|
begin
|
98
101
|
latency = (Time.now - start) * 1000.0
|
99
102
|
# Disable impressions if @config.impressions_queue_size == -1
|
100
|
-
split && store_impression(split_name, matching_key, bucketing_key, treatment_data, store_impressions)
|
103
|
+
split && store_impression(split_name, matching_key, bucketing_key, treatment_data, store_impressions, attributes)
|
101
104
|
|
102
105
|
# Measure
|
103
106
|
@adapter.metrics.time('sdk.get_treatment', latency)
|
@@ -106,8 +109,8 @@ module SplitIoClient
|
|
106
109
|
|
107
110
|
store_impression(
|
108
111
|
split_name, matching_key, bucketing_key,
|
109
|
-
{ treatment: SplitIoClient::Engine::Models::Treatment::CONTROL, label: Engine::Models::Label::EXCEPTION },
|
110
|
-
store_impressions
|
112
|
+
{ treatment: SplitIoClient::Engine::Models::Treatment::CONTROL, label: SplitIoClient::Engine::Models::Label::EXCEPTION },
|
113
|
+
store_impressions, attributes
|
111
114
|
)
|
112
115
|
|
113
116
|
return parsed_treatment(multiple, treatment_data)
|
@@ -116,7 +119,25 @@ module SplitIoClient
|
|
116
119
|
parsed_treatment(multiple, treatment_data)
|
117
120
|
end
|
118
121
|
|
119
|
-
def
|
122
|
+
def destroy
|
123
|
+
@config.logger.info('Split client shutdown started...') if @config.debug_enabled
|
124
|
+
|
125
|
+
@config.threads[:impressions_sender].raise(SplitIoClient::ImpressionShutdownException)
|
126
|
+
@config.threads.reject { |k, _| k == :impressions_sender }.each do |name, thread|
|
127
|
+
Thread.kill(thread)
|
128
|
+
end
|
129
|
+
|
130
|
+
@metrics_repository.clear
|
131
|
+
@splits_repository.clear
|
132
|
+
@segments_repository.clear
|
133
|
+
|
134
|
+
@config.logger.info('Split client shutdown complete') if @config.debug_enabled
|
135
|
+
end
|
136
|
+
|
137
|
+
def store_impression(split_name, matching_key, bucketing_key, treatment, store_impressions, attributes)
|
138
|
+
time = (Time.now.to_f * 1000.0).to_i
|
139
|
+
route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes) if @config.impression_listener && store_impressions
|
140
|
+
|
120
141
|
return if @config.impressions_queue_size <= 0 || !store_impressions
|
121
142
|
|
122
143
|
@impressions_repository.add(split_name,
|
@@ -124,11 +145,37 @@ module SplitIoClient
|
|
124
145
|
'bucketingKey' => bucketing_key,
|
125
146
|
'treatment' => treatment[:treatment],
|
126
147
|
'label' => @config.labels_enabled ? treatment[:label] : nil,
|
127
|
-
'time' =>
|
148
|
+
'time' => time,
|
128
149
|
'changeNumber' => treatment[:change_number]
|
129
150
|
)
|
130
151
|
end
|
131
152
|
|
153
|
+
def route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
|
154
|
+
impression_router.add(
|
155
|
+
split_name: split_name,
|
156
|
+
matching_key: matching_key,
|
157
|
+
bucketing_key: bucketing_key,
|
158
|
+
time: time,
|
159
|
+
treatment: treatment,
|
160
|
+
attributes: attributes
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
def route_impressions(split_names, matching_key, bucketing_key, time, treatments_labels_change_numbers, attributes)
|
165
|
+
impression_router.add_bulk(
|
166
|
+
split_names: split_names,
|
167
|
+
matching_key: matching_key,
|
168
|
+
bucketing_key: bucketing_key,
|
169
|
+
time: time,
|
170
|
+
treatments_labels_change_numbers: treatments_labels_change_numbers,
|
171
|
+
attributes: attributes
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
def impression_router
|
176
|
+
@impression_router ||= SplitIoClient::ImpressionRouter.new(@config)
|
177
|
+
end
|
178
|
+
|
132
179
|
def keys_from_key(key)
|
133
180
|
case key.class.to_s
|
134
181
|
when 'Hash'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class AttributeMatcher
|
3
|
+
def initialize(attribute, matcher)
|
4
|
+
@attribute = attribute
|
5
|
+
@matcher = matcher
|
6
|
+
end
|
7
|
+
|
8
|
+
def match?(matching_key, bucketing_key = nil, evaluator = nil, attributes = {})
|
9
|
+
if @attribute != nil
|
10
|
+
return false unless attributes
|
11
|
+
|
12
|
+
value = attributes.fetch(@attribute) { |name| attributes[name.to_s] || attributes[name.to_sym] }
|
13
|
+
|
14
|
+
@matcher.match?(value, bucketing_key, nil, nil)
|
15
|
+
else
|
16
|
+
@matcher.match?(matching_key, bucketing_key, evaluator, attributes)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -12,10 +12,10 @@ module SplitIoClient
|
|
12
12
|
@end_value = get_formatted_value attribute_hash[:end_value], true
|
13
13
|
end
|
14
14
|
|
15
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
15
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
16
16
|
matches = false
|
17
|
-
if
|
18
|
-
param_value = get_formatted_value(
|
17
|
+
if !value.nil?
|
18
|
+
param_value = get_formatted_value(value)
|
19
19
|
matches = param_value.is_a?(Integer) ? ((param_value >= @start_value) && (param_value <= @end_value)) : false
|
20
20
|
end
|
21
21
|
|
@@ -9,9 +9,7 @@ module SplitIoClient
|
|
9
9
|
@substr_list = substr_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
13
|
-
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
-
|
12
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
13
|
return false if @substr_list.empty?
|
16
14
|
|
17
15
|
@substr_list.any? { |substr| value.to_s.include? substr }
|
@@ -9,9 +9,7 @@ module SplitIoClient
|
|
9
9
|
@suffix_list = suffix_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
13
|
-
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
-
|
12
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
13
|
return false if @suffix_list.empty?
|
16
14
|
|
17
15
|
@suffix_list.any? { |suffix| value.to_s.end_with? suffix }
|
@@ -9,9 +9,7 @@ module SplitIoClient
|
|
9
9
|
@boolean = boolean
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
13
|
-
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
-
|
12
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
13
|
value = false if value.to_s.downcase == 'false'
|
16
14
|
value = true if value.to_s.downcase == 'true'
|
17
15
|
|
@@ -11,10 +11,10 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
14
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
15
|
matches = false
|
16
|
-
if
|
17
|
-
param_value = get_formatted_value(
|
16
|
+
if !value.nil?
|
17
|
+
param_value = get_formatted_value(value)
|
18
18
|
matches = param_value.is_a?(Integer) ? (param_value == @value) : false
|
19
19
|
end
|
20
20
|
end
|
@@ -11,10 +11,10 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
14
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
15
|
matches = false
|
16
|
-
if
|
17
|
-
param_value = get_formatted_value(
|
16
|
+
if !value.nil?
|
17
|
+
param_value = get_formatted_value(value)
|
18
18
|
matches = param_value.is_a?(Integer) ? (param_value >= @value) : false
|
19
19
|
end
|
20
20
|
end
|
@@ -11,10 +11,10 @@ module SplitIoClient
|
|
11
11
|
@value = get_formatted_value attribute_hash[:value], true
|
12
12
|
end
|
13
13
|
|
14
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
14
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
15
|
matches = false
|
16
|
-
if
|
17
|
-
param_value = get_formatted_value(
|
16
|
+
if !value.nil?
|
17
|
+
param_value = get_formatted_value(value)
|
18
18
|
matches = param_value.is_a?(Integer) ? (param_value <= @value) : false
|
19
19
|
end
|
20
20
|
end
|
@@ -9,9 +9,7 @@ module SplitIoClient
|
|
9
9
|
@regexp_string = @regexp_string.is_a?(Regexp) ? regexp_string : Regexp.new(regexp_string)
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
13
|
-
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
-
|
12
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
13
|
(value =~ @regexp_string) != nil
|
16
14
|
end
|
17
15
|
end
|
@@ -9,9 +9,7 @@ module SplitIoClient
|
|
9
9
|
@prefix_list = prefix_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(_matching_key, _bucketing_key, _evaluator
|
13
|
-
value = data.fetch(@attribute) { |attr| data[attr.to_s] || data[attr.to_sym] }
|
14
|
-
|
12
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
15
13
|
return false if @prefix_list.empty?
|
16
14
|
|
17
15
|
@prefix_list.any? { |prefix| value.to_s.start_with? prefix }
|
@@ -20,16 +20,13 @@ module SplitIoClient
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def match?(
|
23
|
+
def match?(value, _matching_key, _bucketing_key, _evaluator)
|
24
24
|
matches = false
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
if (!whitelist_data.nil? && whitelist_data.key?(@attribute.to_sym))
|
29
|
-
value = whitelist_data[@attribute.to_sym]
|
30
|
-
matches = @whitelist.include?(value)
|
31
|
-
end
|
25
|
+
|
26
|
+
if !value.nil?
|
27
|
+
matches = @whitelist.include?(value)
|
32
28
|
end
|
29
|
+
|
33
30
|
matches
|
34
31
|
end
|
35
32
|
|
@@ -58,7 +58,15 @@ module SplitIoClient
|
|
58
58
|
in_rollout = true
|
59
59
|
end
|
60
60
|
|
61
|
-
|
61
|
+
begin
|
62
|
+
matcher = SplitIoClient::AttributeMatcher.new(
|
63
|
+
condition.data[:matcherGroup][:matchers][0][:keySelector][:attribute],
|
64
|
+
matcher_type(condition)
|
65
|
+
)
|
66
|
+
rescue NoMethodError
|
67
|
+
matcher = SplitIoClient::AttributeMatcher.new(nil, matcher_type(condition))
|
68
|
+
end
|
69
|
+
if matcher.match?(keys[:matching_key], keys[:bucketing_key], self, attributes)
|
62
70
|
key = keys[:bucketing_key] ? keys[:bucketing_key] : keys[:matching_key]
|
63
71
|
result = Splitter.get_treatment(key, split[:seed], condition.partitions, split[:algo])
|
64
72
|
|
@@ -61,6 +61,11 @@ module SplitIoClient
|
|
61
61
|
|
62
62
|
@labels_enabled = opts[:labels_enabled].nil? ? SplitConfig.default_labels_logging : opts[:labels_enabled]
|
63
63
|
|
64
|
+
@impression_listener = opts[:impression_listener]
|
65
|
+
@impression_listener_refresh_rate = opts[:impression_listener_refresh_rate] || SplitConfig.default_impression_listener_refresh_rate
|
66
|
+
|
67
|
+
@threads = {}
|
68
|
+
|
64
69
|
startup_log
|
65
70
|
end
|
66
71
|
|
@@ -153,6 +158,9 @@ module SplitIoClient
|
|
153
158
|
attr_reader :metrics_refresh_rate
|
154
159
|
attr_reader :impressions_refresh_rate
|
155
160
|
|
161
|
+
attr_reader :impression_listener
|
162
|
+
attr_reader :impression_listener_refresh_rate
|
163
|
+
|
156
164
|
#
|
157
165
|
# Wow big the impressions queue is before dropping impressions. -1 to disable it.
|
158
166
|
#
|
@@ -162,6 +170,8 @@ module SplitIoClient
|
|
162
170
|
attr_reader :redis_url
|
163
171
|
attr_reader :redis_namespace
|
164
172
|
|
173
|
+
attr_accessor :threads
|
174
|
+
|
165
175
|
#
|
166
176
|
# The default split client configuration
|
167
177
|
#
|
@@ -251,6 +261,10 @@ module SplitIoClient
|
|
251
261
|
60
|
252
262
|
end
|
253
263
|
|
264
|
+
def self.default_impression_listener_refresh_rate
|
265
|
+
0
|
266
|
+
end
|
267
|
+
|
254
268
|
def self.default_impressions_queue_size
|
255
269
|
5000
|
256
270
|
end
|
@@ -302,7 +316,7 @@ module SplitIoClient
|
|
302
316
|
def log_found_exception(caller, exn)
|
303
317
|
error_traceback = "#{exn.inspect} #{exn}\n\t#{exn.backtrace.join("\n\t")}"
|
304
318
|
error = "[splitclient-rb] Unexpected exception in #{caller}: #{error_traceback}"
|
305
|
-
@logger.
|
319
|
+
@logger.warn(error)
|
306
320
|
end
|
307
321
|
|
308
322
|
#
|
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: 4.
|
4
|
+
version: 4.3.0.canary.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -266,6 +266,7 @@ files:
|
|
266
266
|
- lib/splitclient-rb/cache/repositories/repository.rb
|
267
267
|
- lib/splitclient-rb/cache/repositories/segments_repository.rb
|
268
268
|
- lib/splitclient-rb/cache/repositories/splits_repository.rb
|
269
|
+
- lib/splitclient-rb/cache/routers/impression_router.rb
|
269
270
|
- lib/splitclient-rb/cache/senders/impressions_formatter.rb
|
270
271
|
- lib/splitclient-rb/cache/senders/impressions_sender.rb
|
271
272
|
- lib/splitclient-rb/cache/senders/metrics_sender.rb
|
@@ -282,6 +283,7 @@ files:
|
|
282
283
|
- lib/splitclient-rb/engine/api/splits.rb
|
283
284
|
- lib/splitclient-rb/engine/evaluator/splitter.rb
|
284
285
|
- lib/splitclient-rb/engine/matchers/all_keys_matcher.rb
|
286
|
+
- lib/splitclient-rb/engine/matchers/attribute_matcher.rb
|
285
287
|
- lib/splitclient-rb/engine/matchers/between_matcher.rb
|
286
288
|
- lib/splitclient-rb/engine/matchers/combiners.rb
|
287
289
|
- lib/splitclient-rb/engine/matchers/combining_matcher.rb
|
@@ -311,6 +313,7 @@ files:
|
|
311
313
|
- lib/splitclient-rb/engine/parser/evaluator.rb
|
312
314
|
- lib/splitclient-rb/engine/parser/partition.rb
|
313
315
|
- lib/splitclient-rb/engine/parser/split_adapter.rb
|
316
|
+
- lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb
|
314
317
|
- lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb
|
315
318
|
- lib/splitclient-rb/localhost_split_factory.rb
|
316
319
|
- lib/splitclient-rb/localhost_utils.rb
|
@@ -343,9 +346,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
343
346
|
version: '0'
|
344
347
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
345
348
|
requirements:
|
346
|
-
- - "
|
349
|
+
- - ">"
|
347
350
|
- !ruby/object:Gem::Version
|
348
|
-
version:
|
351
|
+
version: 1.3.1
|
349
352
|
requirements: []
|
350
353
|
rubyforge_project:
|
351
354
|
rubygems_version: 2.5.2
|