splitclient-rb 6.1.0.pre.rc2-java → 6.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -0
- data/Appraisals +10 -0
- data/CHANGES.txt +19 -1
- data/Detailed-README.md +56 -6
- data/NEWS +13 -2
- data/Rakefile +8 -1
- data/gemfiles/faraday_after_0.13.gemfile +7 -0
- data/gemfiles/faraday_before_0.13.gemfile +8 -0
- data/lib/splitclient-rb.rb +1 -0
- data/lib/splitclient-rb/cache/adapters/cache_adapter.rb +0 -1
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +2 -3
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +4 -0
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +14 -2
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +1 -1
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +4 -0
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +10 -2
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +1 -1
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +1 -1
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +1 -1
- data/lib/splitclient-rb/cache/senders/events_sender.rb +12 -5
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +3 -2
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +7 -8
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +10 -4
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +2 -3
- 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 +7 -5
- data/lib/splitclient-rb/engine/api/client.rb +21 -0
- data/lib/splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent.rb +46 -0
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +1 -1
- data/lib/splitclient-rb/exceptions.rb +1 -1
- data/lib/splitclient-rb/split_config.rb +2 -2
- data/lib/splitclient-rb/split_factory.rb +16 -14
- data/lib/splitclient-rb/version.rb +1 -1
- data/splitclient-rb.gemspec +1 -0
- metadata +22 -5
- data/tasks/rspec.rake +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dfdae505c0eca2e3987d5af60da4daa5702c174
|
4
|
+
data.tar.gz: f9aff992da65d89442e89a77d77a263598210c7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9539acd2c6c11b81e492d850841d65d0e30c9fe6e7498600103daab76ca461ba306c1729cb079797b0a672ffb9e02c014343fab574722e3e48a4f28d4ec9ae06
|
7
|
+
data.tar.gz: c2d7ae820b2833adc610bf8e4e64d7fd7c83c18ea113900b98165e18dcb0ebf7fa68195e8510404dca35d0ecefa56c5579caecd6434d712d92364d9b3f7f7dc4
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/Appraisals
ADDED
data/CHANGES.txt
CHANGED
@@ -1,11 +1,29 @@
|
|
1
|
+
6.2.0 (Mar 7th, 2019)
|
2
|
+
- Reworked SplitClient#destroy to ensure events, impressions and metrics are sent to Split backend when called
|
3
|
+
- Ensured destroy is called when keyboard interrupts are sent to the application
|
4
|
+
- Changed SDK blocker (and block_until_ready) to have no effect in consumer mode
|
5
|
+
- Added support for applications tied to Faraday < 0.13 and net-http-persistent 3 using a patched Faraday adapter
|
6
|
+
- Added documentation for input validation in detailed readme
|
7
|
+
- Changed SplitConfig#default_features_refresh_rate value to 5 seconds
|
8
|
+
|
9
|
+
6.1.0 (Feb 8th, 2019)
|
10
|
+
- Review input validation for client API methods. Better control and logging over nil, empty, numeric, and NaN parameters
|
11
|
+
- Added logging when block_until_ready is not set or api key is not provided
|
12
|
+
- Reviewed client API methods to log an error and return nil / empty when called after client was destroyed
|
13
|
+
- Update track regex and fix an error causing a partial match to pass as a valid event_type
|
14
|
+
- Add logging to #match? in matcher subclasses
|
15
|
+
- Fix simplecov configuration issue causing errors in coverage calculation
|
16
|
+
- Improve code coverage and decrease rubocop violation count
|
17
|
+
- Fix for issue causing redis_url parameter to be ignored and Redis to always default to REDIS_ENV environment variable
|
18
|
+
|
1
19
|
6.0.1 (Jan 7th, 2019)
|
2
20
|
- Fix an issue in events and impressions API calls log messages caused by a wrong variable name introduced in 6.0.0
|
3
21
|
|
4
22
|
6.0.0 (December 17th, 2018)
|
23
|
+
- BREAKING CHANGE: Change format used to store impressions in repositories to reduce the number of Redis operations. It requires an update of the Split Synchronizer to >2.0.0 if you're using Redis mode.
|
5
24
|
- Change `sender` and `store` classes to reuse Faraday connections, preventing issues with net-http-persistent 3.0
|
6
25
|
- Remove producer mode and make `memory + standalone` and `Redis + consumer` the only valid SDK modes. This is a breaking change
|
7
26
|
- Fix `evaluator` bucket calculation when traffic allocation is set to 1%
|
8
|
-
- Change format used to store impressions in repositories to reduce the number of Redis operations
|
9
27
|
- Add cache wrapper to `segments_repository` and `splits_repository` to reduce the number of Redis operations
|
10
28
|
- Add `cache_ttl` and `max_cache_size` options to setup the memory cache wrapper when using redis
|
11
29
|
|
data/Detailed-README.md
CHANGED
@@ -206,6 +206,57 @@ The split client will return `on`. Note that this will be true for any bucketing
|
|
206
206
|
factory = SplitIoClient::SplitFactoryBuilder.build('localhost', path: '/where/to-look-for/<file_name>', reload_rate: 3)
|
207
207
|
```
|
208
208
|
|
209
|
+
### SDK Input Validations
|
210
|
+
|
211
|
+
In order to provide consistency among the SDKs for the different programming languages, provide better output to users in case of errors, and prevent unexpected errors to raise exceptions in your application, most of the parameters in the SDK methods are validated against a set of rules. Similarly, some of the configuration parameters must follow these rules, too. Check your application against the list below to prevent issues when using the SDK.
|
212
|
+
|
213
|
+
#### get_treatment (split_client)
|
214
|
+
|
215
|
+
- `key` (when not using matching_key and bucketing_key): must be a non-empty `String` or a `Symbol`, shorter than 250 characters. If a non-NaN `Numeric` value is used, it'll be converted to its `String` representation.
|
216
|
+
|
217
|
+
- `matching_key`, `bucketing_key`: the containing `Hash` must have both keys, and the same rules above apply for each.
|
218
|
+
|
219
|
+
- `split_name`: must be a non-empty `String` or a `Symbol`. Whitespaces will be trimmed from both ends of it. The trimmed version of the `split_name` will be used for both evaluation and to store the resulting impression.
|
220
|
+
|
221
|
+
- `attributes`: must be of type `Hash`.
|
222
|
+
|
223
|
+
#### get_treatments (split_client)
|
224
|
+
|
225
|
+
- `key`, `matching_key`, `bucketing_key`: same rules as those for `get_treatment` apply.
|
226
|
+
|
227
|
+
- `split_names`: must be an non-empty Array. Split names will be filtered removing those not matching the corresponding rules for `split_name` in `get_treatment`. In addition, duplicates will be removed.
|
228
|
+
|
229
|
+
#### track (split_client)
|
230
|
+
|
231
|
+
- `key`: must be a non-empty `String` or a `Symbol`, shorter than 250 characters. If a non-NaN `Numeric` value is used, it'll be converted to its `String` representation.
|
232
|
+
|
233
|
+
- `traffic_type_name`: must be a non-empty `String` or a `Symbol`. If `traffic_type_name` contains uppercase letters, it will be lowercased.
|
234
|
+
|
235
|
+
- `event_type`: must be a non-empty `String` or `Symbol` that conforms with the regular expression `^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$` (i.e. event name must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters).
|
236
|
+
|
237
|
+
- `value`: must be either a non-NaN `Numeric` value, or nil.
|
238
|
+
|
239
|
+
#### split (split_manager)
|
240
|
+
|
241
|
+
- `split_name`: must be a non-empty `String` or a `Symbol`.
|
242
|
+
|
243
|
+
#### Configuration Parameters
|
244
|
+
|
245
|
+
- `api_key`: must be a non-empty `String` or a `Symbol` of type `sdk` (`browser` type API keys will break this rule).
|
246
|
+
|
247
|
+
- `block_until_ready`: a warning log message will be issued if this value is not set.
|
248
|
+
|
249
|
+
|
250
|
+
#### Client Destroyed Rules
|
251
|
+
Calls to the SDK methods are still possible after `destroy` is called. All will log an error message stating _client has been destroyed_.
|
252
|
+
|
253
|
+
- `get_treatment` will return `control` for all calls (`get_treatments`, will return an Array of `control` values, correspondingly).
|
254
|
+
|
255
|
+
- Calls to `track` will return `false`.
|
256
|
+
|
257
|
+
- All calls to `split_manager` methods will return an empty Array, except `split`, which will return `nil`.
|
258
|
+
|
259
|
+
|
209
260
|
## Advanced Configuration
|
210
261
|
|
211
262
|
Split client's default configuration should cover most scenarios. However, you can also provide custom configuration settings when initializing the factory using a hash of options. e.g.:
|
@@ -236,7 +287,7 @@ The following values can be customized:
|
|
236
287
|
|
237
288
|
**features_refresh_rate** : The SDK polls Split servers for changes to feature Splits every X seconds, where X is this property's value.
|
238
289
|
|
239
|
-
*default value* = `
|
290
|
+
*default value* = `5`
|
240
291
|
|
241
292
|
**segments_refresh_rate** : The SDK polls Split servers for changes to segments every X seconds, where X is this property's value.
|
242
293
|
|
@@ -280,6 +331,8 @@ The following values can be customized:
|
|
280
331
|
|
281
332
|
**block_until_ready** : The SDK will block your app for the provided amount of seconds until it's ready. A `SplitIoClient::SDKBlockerTimeoutExpiredException` will be thrown If the provided time expires. When `0` is provided, the SDK runs in non-blocking mode.
|
282
333
|
|
334
|
+
_When using consumer mode, blocking has no effect._
|
335
|
+
|
283
336
|
*default value* = `0`
|
284
337
|
|
285
338
|
**labels_enabled** : Allows preventing labels from being sent to the Split servers, as they may contain sensitive information.
|
@@ -349,11 +402,8 @@ options = {
|
|
349
402
|
mode: :consumer,
|
350
403
|
redis_url: 'redis://127.0.0.1:6379/0'
|
351
404
|
}
|
352
|
-
|
353
|
-
|
354
|
-
rescue SplitIoClient::SDKBlockerTimeoutExpiredException
|
355
|
-
# Code to treat raised exception
|
356
|
-
end
|
405
|
+
|
406
|
+
split_client = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY', options).client
|
357
407
|
```
|
358
408
|
|
359
409
|
### Logging
|
data/NEWS
CHANGED
@@ -1,11 +1,22 @@
|
|
1
|
+
6.2.0
|
2
|
+
Ensure SDK flushes information to Split servers on client destroy
|
3
|
+
Fix for compatibility issue between Faraday < 0.13 and net-http-persistent 3
|
4
|
+
Change default features refresh rate interval to 5 seconds
|
5
|
+
|
6
|
+
6.1.0
|
7
|
+
|
8
|
+
Review input validation for client API methods: get_treatment, get_treatments, track, manager. Add input validation to block_until_ready, client startup, and destroy
|
9
|
+
Add additional logging to the SDK Client in order to help debug matcher related issues
|
10
|
+
Fix for issue causing redis_url parameter to be ignored
|
11
|
+
|
1
12
|
6.0.1
|
2
13
|
|
3
14
|
Fix an issue in events and impressions API calls log messages introduced in 6.0.0
|
4
15
|
|
5
16
|
6.0.0
|
6
17
|
|
7
|
-
Remove producer mode, make memory adapter mandatory in standalone mode, and Redis adapter mandatory in consumer mode.
|
8
|
-
Reduce the total number of Redis operations of the SDK by changing the impressions storage format and adding a memory cache for splits and segments.
|
18
|
+
BREAKING CHANGE: Remove producer mode, make memory adapter mandatory in standalone mode, and Redis adapter mandatory in consumer mode.
|
19
|
+
BREAKING CHANGE: Reduce the total number of Redis operations of the SDK by changing the impressions storage format and adding a memory cache for splits and segments. It requires to have Split Synchronizer > v2.0.0 running if you are using Redis.
|
9
20
|
SDK is now compatible with net-http-persistent 3.0.
|
10
21
|
|
11
22
|
5.1.2
|
data/Rakefile
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
4
|
require 'rspec/core/rake_task'
|
5
5
|
require 'rubocop/rake_task'
|
6
|
+
require 'appraisal'
|
6
7
|
|
7
8
|
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
8
9
|
|
@@ -25,4 +26,10 @@ else
|
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
|
-
|
29
|
+
if !ENV['APPRAISAL_INITIALIZED']
|
30
|
+
task :default do
|
31
|
+
sh 'appraisal install && rake appraisal && rake rubocop'
|
32
|
+
end
|
33
|
+
else
|
34
|
+
task default: %i[spec rubocop]
|
35
|
+
end
|
data/lib/splitclient-rb.rb
CHANGED
@@ -41,6 +41,7 @@ require 'splitclient-rb/split_config'
|
|
41
41
|
require 'splitclient-rb/split_logger'
|
42
42
|
|
43
43
|
require 'splitclient-rb/engine/api/faraday_middleware/gzip'
|
44
|
+
require 'splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent'
|
44
45
|
require 'splitclient-rb/engine/api/client'
|
45
46
|
require 'splitclient-rb/engine/api/impressions'
|
46
47
|
require 'splitclient-rb/engine/api/metrics'
|
@@ -125,6 +125,7 @@ module SplitIoClient
|
|
125
125
|
@redis.rpush(key, val)
|
126
126
|
end
|
127
127
|
|
128
|
+
# count = 0 will result in lrange(0,-1), fetching all items
|
128
129
|
def get_from_queue(key, count)
|
129
130
|
items = @redis.lrange(key, 0, count - 1)
|
130
131
|
fetched_count = items.size
|
@@ -157,9 +158,7 @@ module SplitIoClient
|
|
157
158
|
end
|
158
159
|
|
159
160
|
def clear(prefix)
|
160
|
-
|
161
|
-
|
162
|
-
keys.map { |key| @redis.del(key) }
|
161
|
+
# noop
|
163
162
|
end
|
164
163
|
|
165
164
|
def expire(key, seconds)
|
@@ -16,11 +16,23 @@ module SplitIoClient
|
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
@adapter.get_from_queue(namespace_key('.events'),
|
19
|
+
def get_events(number_of_events = 0)
|
20
|
+
@adapter.get_from_queue(namespace_key('.events'), number_of_events).map do |e|
|
21
21
|
JSON.parse(e, symbolize_names: true)
|
22
22
|
end
|
23
|
+
rescue StandardError => e
|
24
|
+
SplitIoClient.configuration.logger.error("Exception while clearing events cache: #{e}")
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
def batch
|
29
|
+
get_events(EVENTS_SLICE)
|
23
30
|
end
|
31
|
+
|
32
|
+
def clear
|
33
|
+
get_events
|
34
|
+
end
|
35
|
+
|
24
36
|
end
|
25
37
|
end
|
26
38
|
end
|
@@ -4,7 +4,7 @@ module SplitIoClient
|
|
4
4
|
# Repository which forwards events interface to the selected adapter
|
5
5
|
class EventsRepository < Repository
|
6
6
|
extend Forwardable
|
7
|
-
def_delegators :@adapter, :add, :clear
|
7
|
+
def_delegators :@adapter, :add, :clear, :batch
|
8
8
|
|
9
9
|
def initialize(adapter)
|
10
10
|
@adapter = case adapter.class.to_s
|
@@ -35,8 +35,8 @@ module SplitIoClient
|
|
35
35
|
@adapter.expire(key, EXPIRE_SECONDS) if impressions.size == impressions_list_size
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
@adapter.get_from_queue(key,
|
38
|
+
def get_impressions(number_of_impressions = 0)
|
39
|
+
@adapter.get_from_queue(key, number_of_impressions).map do |e|
|
40
40
|
impression = JSON.parse(e, symbolize_names: true)
|
41
41
|
impression[:i][:f] = impression[:i][:f].to_sym
|
42
42
|
impression
|
@@ -46,6 +46,14 @@ module SplitIoClient
|
|
46
46
|
[]
|
47
47
|
end
|
48
48
|
|
49
|
+
def batch
|
50
|
+
get_impressions(SplitIoClient.configuration.impressions_bulk_size)
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear
|
54
|
+
get_impressions
|
55
|
+
end
|
56
|
+
|
49
57
|
def key
|
50
58
|
@key ||= namespace_key('.impressions')
|
51
59
|
end
|
@@ -6,7 +6,7 @@ module SplitIoClient
|
|
6
6
|
# Repository which forwards impressions interface to the selected adapter
|
7
7
|
class ImpressionsRepository < Repository
|
8
8
|
extend Forwardable
|
9
|
-
def_delegators :@adapter, :add, :add_bulk, :batch, :empty?
|
9
|
+
def_delegators :@adapter, :add, :add_bulk, :batch, :clear, :empty?
|
10
10
|
|
11
11
|
def initialize(adapter)
|
12
12
|
@adapter = case adapter.class.to_s
|
@@ -13,7 +13,7 @@ module SplitIoClient
|
|
13
13
|
else
|
14
14
|
adapter
|
15
15
|
end
|
16
|
-
@adapter.set_bool(namespace_key('.ready'), false) unless SplitIoClient.configuration.mode
|
16
|
+
@adapter.set_bool(namespace_key('.ready'), false) unless SplitIoClient.configuration.mode.equal?(:consumer)
|
17
17
|
end
|
18
18
|
|
19
19
|
# Receives segment data, adds and removes segements from the store
|
@@ -13,7 +13,7 @@ module SplitIoClient
|
|
13
13
|
else
|
14
14
|
adapter
|
15
15
|
end
|
16
|
-
unless SplitIoClient.configuration.mode
|
16
|
+
unless SplitIoClient.configuration.mode.equal?(:consumer)
|
17
17
|
@adapter.set_string(namespace_key('.splits.till'), '-1')
|
18
18
|
@adapter.initialize_map(namespace_key('.segments.registered'))
|
19
19
|
end
|
@@ -27,18 +27,25 @@ module SplitIoClient
|
|
27
27
|
|
28
28
|
def events_thread
|
29
29
|
SplitIoClient.configuration.threads[:events_sender] = Thread.new do
|
30
|
-
|
30
|
+
begin
|
31
|
+
SplitIoClient.configuration.logger.info('Starting events service')
|
32
|
+
|
33
|
+
loop do
|
34
|
+
post_events(false)
|
31
35
|
|
32
|
-
|
36
|
+
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.events_push_rate))
|
37
|
+
end
|
38
|
+
rescue SplitIoClient::SDKShutdownException
|
33
39
|
post_events
|
34
40
|
|
35
|
-
|
41
|
+
SplitIoClient.configuration.logger.info('Posting events due to shutdown')
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
39
45
|
|
40
|
-
def post_events
|
41
|
-
|
46
|
+
def post_events(fetch_all_events = true)
|
47
|
+
events = fetch_all_events ? @events_repository.clear : @events_repository.batch
|
48
|
+
events_api.post(events)
|
42
49
|
rescue StandardError => error
|
43
50
|
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
44
51
|
end
|
@@ -8,8 +8,9 @@ module SplitIoClient
|
|
8
8
|
@impressions_repository = impressions_repository
|
9
9
|
end
|
10
10
|
|
11
|
-
def call(raw_impressions)
|
12
|
-
impressions = raw_impressions || @impressions_repository.batch
|
11
|
+
def call(fetch_all_impressions, raw_impressions = nil)
|
12
|
+
impressions = raw_impressions || (fetch_all_impressions ? @impressions_repository.clear : @impressions_repository.batch)
|
13
|
+
|
13
14
|
filtered_impressions = filter_impressions(impressions)
|
14
15
|
|
15
16
|
return [] if impressions.empty? || filtered_impressions.empty?
|
@@ -36,28 +36,27 @@ module SplitIoClient
|
|
36
36
|
SplitIoClient.configuration.logger.info('Starting impressions service')
|
37
37
|
|
38
38
|
loop do
|
39
|
-
post_impressions
|
39
|
+
post_impressions(false)
|
40
40
|
|
41
41
|
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.impressions_refresh_rate))
|
42
42
|
end
|
43
|
-
rescue SplitIoClient::
|
43
|
+
rescue SplitIoClient::SDKShutdownException
|
44
44
|
post_impressions
|
45
45
|
|
46
|
-
|
46
|
+
SplitIoClient.configuration.logger.info('Posting impressions due to shutdown')
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def post_impressions
|
51
|
+
def post_impressions(fetch_all_impressions = true)
|
52
|
+
formatted_impressions = ImpressionsFormatter.new(@impressions_repository)
|
53
|
+
.call(fetch_all_impressions)
|
54
|
+
|
52
55
|
impressions_api.post(formatted_impressions)
|
53
56
|
rescue StandardError => error
|
54
57
|
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
55
58
|
end
|
56
59
|
|
57
|
-
def formatted_impressions(raw_impressions = nil)
|
58
|
-
ImpressionsFormatter.new(@impressions_repository).call(raw_impressions)
|
59
|
-
end
|
60
|
-
|
61
60
|
def impressions_api
|
62
61
|
@impressions_api ||= SplitIoClient::Api::Impressions.new(@api_key)
|
63
62
|
end
|
@@ -25,12 +25,18 @@ module SplitIoClient
|
|
25
25
|
|
26
26
|
def metrics_thread
|
27
27
|
SplitIoClient.configuration.threads[:metrics_sender] = Thread.new do
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
begin
|
29
|
+
SplitIoClient.configuration.logger.info('Starting metrics service')
|
30
|
+
|
31
|
+
loop do
|
32
|
+
post_metrics
|
33
|
+
|
34
|
+
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.metrics_refresh_rate))
|
35
|
+
end
|
36
|
+
rescue SplitIoClient::SDKShutdownException
|
31
37
|
post_metrics
|
32
38
|
|
33
|
-
|
39
|
+
SplitIoClient.configuration.logger.info('Posting metrics due to shutdown')
|
34
40
|
end
|
35
41
|
end
|
36
42
|
end
|
@@ -6,7 +6,6 @@ module SplitIoClient
|
|
6
6
|
module Stores
|
7
7
|
class SDKBlocker
|
8
8
|
attr_reader :splits_repository
|
9
|
-
attr_writer :splits_thread, :segments_thread
|
10
9
|
|
11
10
|
def initialize(splits_repository, segments_repository)
|
12
11
|
@splits_repository = splits_repository
|
@@ -34,8 +33,8 @@ module SplitIoClient
|
|
34
33
|
end
|
35
34
|
|
36
35
|
SplitIoClient.configuration.logger.info('SplitIO SDK is ready')
|
37
|
-
|
38
|
-
|
36
|
+
SplitIoClient.configuration.threads[:split_store].run
|
37
|
+
SplitIoClient.configuration.threads[:segment_store].run
|
39
38
|
end
|
40
39
|
|
41
40
|
def ready?
|
@@ -28,7 +28,7 @@ module SplitIoClient
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def segments_thread
|
31
|
-
SplitIoClient.configuration.threads[:segment_store] =
|
31
|
+
SplitIoClient.configuration.threads[:segment_store] = Thread.new do
|
32
32
|
SplitIoClient.configuration.logger.info('Starting segments fetcher service')
|
33
33
|
SplitIoClient.configuration.block_until_ready > 0 ? blocked_store : unblocked_store
|
34
34
|
end
|
@@ -28,7 +28,7 @@ module SplitIoClient
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def splits_thread
|
31
|
-
SplitIoClient.configuration.threads[:split_store] =
|
31
|
+
SplitIoClient.configuration.threads[:split_store] = Thread.new do
|
32
32
|
SplitIoClient.configuration.logger.info('Starting splits fetcher service')
|
33
33
|
loop do
|
34
34
|
store_splits
|
@@ -125,14 +125,16 @@ module SplitIoClient
|
|
125
125
|
|
126
126
|
def destroy
|
127
127
|
SplitIoClient.configuration.logger.info('Split client shutdown started...') if SplitIoClient.configuration.debug_enabled
|
128
|
-
|
129
|
-
SplitIoClient.configuration.threads.
|
130
|
-
|
128
|
+
|
129
|
+
SplitIoClient.configuration.threads.select { |name, thread| name.to_s.end_with? 'sender' }.values.each do |thread|
|
130
|
+
thread.raise(SplitIoClient::SDKShutdownException)
|
131
|
+
thread.join
|
131
132
|
end
|
132
|
-
|
133
|
+
|
134
|
+
SplitIoClient.configuration.threads.values.each { |thread| Thread.kill(thread) }
|
135
|
+
|
133
136
|
@splits_repository.clear
|
134
137
|
@segments_repository.clear
|
135
|
-
@events_repository.clear
|
136
138
|
|
137
139
|
SplitIoClient.configuration.logger.info('Split client shutdown complete') if SplitIoClient.configuration.debug_enabled
|
138
140
|
SplitIoClient.configuration.valid_mode = false
|
@@ -43,12 +43,33 @@ module SplitIoClient
|
|
43
43
|
private
|
44
44
|
|
45
45
|
def api_client
|
46
|
+
if needs_patched_net_http_persistent_adapter?
|
47
|
+
require 'splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent'
|
48
|
+
|
49
|
+
Faraday::Adapter.register_middleware(
|
50
|
+
net_http_persistent: SplitIoClient::FaradayAdapter::PatchedNetHttpPersistent
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
46
54
|
@api_client ||= Faraday.new do |builder|
|
47
55
|
builder.use SplitIoClient::FaradayMiddleware::Gzip
|
48
56
|
builder.adapter :net_http_persistent
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
60
|
+
def needs_patched_net_http_persistent_adapter?
|
61
|
+
new_net_http_persistent? && incompatible_faraday_version?
|
62
|
+
end
|
63
|
+
|
64
|
+
def incompatible_faraday_version?
|
65
|
+
version = Faraday::VERSION.split('.')[0..1]
|
66
|
+
version[0].to_i == 0 && version[1].to_i < 13
|
67
|
+
end
|
68
|
+
|
69
|
+
def new_net_http_persistent?
|
70
|
+
Net::HTTP::Persistent::VERSION.split('.').first.to_i >= 3
|
71
|
+
end
|
72
|
+
|
52
73
|
def common_headers(api_key)
|
53
74
|
{
|
54
75
|
'Authorization' => "Bearer #{api_key}",
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module FaradayAdapter
|
5
|
+
class PatchedNetHttpPersistent < Faraday::Adapter::NetHttpPersistent
|
6
|
+
##
|
7
|
+
# Borrowed directly from the latest `NetHttpPersistent` adapter implementation.
|
8
|
+
#
|
9
|
+
# https://github.com/lostisland/faraday/blob/master/lib/faraday/adapter/net_http_persistent.rb
|
10
|
+
#
|
11
|
+
def net_http_connection(env)
|
12
|
+
@cached_connection ||=
|
13
|
+
if Net::HTTP::Persistent.instance_method(:initialize).parameters.first == [:key, :name]
|
14
|
+
Net::HTTP::Persistent.new(name: 'Faraday')
|
15
|
+
else
|
16
|
+
Net::HTTP::Persistent.new('Faraday')
|
17
|
+
end
|
18
|
+
|
19
|
+
proxy_uri = proxy_uri(env)
|
20
|
+
@cached_connection.proxy = proxy_uri if @cached_connection.proxy_uri != proxy_uri
|
21
|
+
@cached_connection
|
22
|
+
end
|
23
|
+
|
24
|
+
def proxy_uri(env)
|
25
|
+
proxy_uri = nil
|
26
|
+
if (proxy = env[:request][:proxy])
|
27
|
+
proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
|
28
|
+
proxy_uri.user = proxy_uri.password = nil
|
29
|
+
# awful patch for net-http-persistent 2.8 not unescaping user/password
|
30
|
+
(
|
31
|
+
class << proxy_uri;
|
32
|
+
self;
|
33
|
+
end).class_eval do
|
34
|
+
define_method(:user) { proxy[:user] }
|
35
|
+
define_method(:password) { proxy[:password] }
|
36
|
+
end if proxy[:user]
|
37
|
+
end
|
38
|
+
proxy_uri
|
39
|
+
end
|
40
|
+
|
41
|
+
def with_net_http_connection(env)
|
42
|
+
yield net_http_connection(env)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -20,7 +20,7 @@ module SplitIoClient
|
|
20
20
|
# @param splits_repository [SplitsRepository] SplitsRepository instance to store splits in
|
21
21
|
# @param segments_repository [SegmentsRepository] SegmentsRepository instance to store segments in
|
22
22
|
# @param impressions_repository [ImpressionsRepository] ImpressionsRepository instance to store impressions in
|
23
|
-
# @param metrics_repository [MetricsRepository]
|
23
|
+
# @param metrics_repository [MetricsRepository] MetricsRepository instance to store metrics in
|
24
24
|
# @param sdk_blocker [SDKBlocker] SDKBlocker instance which blocks splits_repository/segments_repository
|
25
25
|
#
|
26
26
|
# @return [SplitIoClient] split.io client instance
|
@@ -70,7 +70,7 @@ module SplitIoClient
|
|
70
70
|
@transport_debug_enabled = opts[:transport_debug_enabled] || SplitConfig.default_debug
|
71
71
|
@block_until_ready = opts[:ready] || opts[:block_until_ready] || 0
|
72
72
|
|
73
|
-
@logger.warn 'no ready parameter has been set - incorrect control treatments could be logged' if block_until_ready == 0
|
73
|
+
@logger.warn 'no ready parameter has been set - incorrect control treatments could be logged' if block_until_ready == 0 && !mode.equal?(:consumer)
|
74
74
|
|
75
75
|
@machine_name = opts[:machine_name] || SplitConfig.machine_hostname
|
76
76
|
@machine_ip = opts[:machine_ip] || SplitConfig.machine_ip
|
@@ -304,7 +304,7 @@ module SplitIoClient
|
|
304
304
|
end
|
305
305
|
|
306
306
|
def self.default_features_refresh_rate
|
307
|
-
|
307
|
+
5
|
308
308
|
end
|
309
309
|
|
310
310
|
def self.default_segments_refresh_rate
|
@@ -7,6 +7,17 @@ module SplitIoClient
|
|
7
7
|
attr_reader :adapter, :client, :manager
|
8
8
|
|
9
9
|
def initialize(api_key, config_hash = {})
|
10
|
+
at_exit do
|
11
|
+
unless ENV['SPLITCLIENT_ENV'] == 'test'
|
12
|
+
if (Process.pid == ROOT_PROCESS_ID)
|
13
|
+
SplitIoClient.configuration.logger.info('Split SDK shutdown started...')
|
14
|
+
@client.destroy if @client
|
15
|
+
stop!
|
16
|
+
SplitIoClient.configuration.logger.info('Split SDK shutdown complete')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
10
21
|
@api_key = api_key
|
11
22
|
SplitIoClient.configure(config_hash)
|
12
23
|
|
@@ -20,7 +31,10 @@ module SplitIoClient
|
|
20
31
|
@metrics_repository = MetricsRepository.new(SplitIoClient.configuration.metrics_adapter)
|
21
32
|
@events_repository = EventsRepository.new(SplitIoClient.configuration.events_adapter)
|
22
33
|
|
23
|
-
|
34
|
+
if SplitIoClient.configuration.mode == :standalone && SplitIoClient.configuration.block_until_ready > 0
|
35
|
+
@sdk_blocker = SDKBlocker.new(@splits_repository, @segments_repository)
|
36
|
+
end
|
37
|
+
|
24
38
|
@adapter = start!
|
25
39
|
|
26
40
|
@client = SplitClient.new(@api_key, @adapter, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @events_repository)
|
@@ -28,19 +42,7 @@ module SplitIoClient
|
|
28
42
|
|
29
43
|
validate_api_key
|
30
44
|
|
31
|
-
@sdk_blocker.block if
|
32
|
-
|
33
|
-
|
34
|
-
at_exit do
|
35
|
-
unless ENV['SPLITCLIENT_ENV'] == 'test'
|
36
|
-
if (Process.pid == ROOT_PROCESS_ID)
|
37
|
-
SplitIoClient.configuration.logger.info('Split SDK shutdown started...')
|
38
|
-
@client.destroy
|
39
|
-
stop!
|
40
|
-
SplitIoClient.configuration.logger.info('Split SDK shutdown complete')
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
45
|
+
@sdk_blocker.block if @sdk_blocker
|
44
46
|
end
|
45
47
|
|
46
48
|
def start!
|
data/splitclient-rb.gemspec
CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
end
|
37
37
|
|
38
38
|
spec.add_development_dependency 'allocation_stats'
|
39
|
+
spec.add_development_dependency 'appraisal'
|
39
40
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
40
41
|
spec.add_development_dependency 'pry'
|
41
42
|
spec.add_development_dependency 'pry-nav'
|
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: 6.
|
4
|
+
version: 6.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
name: appraisal
|
34
|
+
prerelease: false
|
35
|
+
type: :development
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
29
43
|
requirements:
|
@@ -272,6 +286,7 @@ files:
|
|
272
286
|
- ".gitignore"
|
273
287
|
- ".rubocop.yml"
|
274
288
|
- ".simplecov"
|
289
|
+
- Appraisals
|
275
290
|
- CHANGES.txt
|
276
291
|
- Detailed-README.md
|
277
292
|
- Gemfile
|
@@ -280,6 +295,8 @@ files:
|
|
280
295
|
- README.md
|
281
296
|
- Rakefile
|
282
297
|
- ext/murmurhash/MurmurHash3.java
|
298
|
+
- gemfiles/faraday_after_0.13.gemfile
|
299
|
+
- gemfiles/faraday_before_0.13.gemfile
|
283
300
|
- lib/murmurhash/base.rb
|
284
301
|
- lib/murmurhash/murmurhash.jar
|
285
302
|
- lib/murmurhash/murmurhash_mri.rb
|
@@ -313,6 +330,7 @@ files:
|
|
313
330
|
- lib/splitclient-rb/clients/split_client.rb
|
314
331
|
- lib/splitclient-rb/engine/api/client.rb
|
315
332
|
- lib/splitclient-rb/engine/api/events.rb
|
333
|
+
- lib/splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent.rb
|
316
334
|
- lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb
|
317
335
|
- lib/splitclient-rb/engine/api/impressions.rb
|
318
336
|
- lib/splitclient-rb/engine/api/metrics.rb
|
@@ -365,7 +383,6 @@ files:
|
|
365
383
|
- splitclient-rb.gemspec
|
366
384
|
- tasks/benchmark_get_treatment.rake
|
367
385
|
- tasks/irb.rake
|
368
|
-
- tasks/rspec.rake
|
369
386
|
homepage: https://github.com/splitio/ruby-client
|
370
387
|
licenses:
|
371
388
|
- Apache 2.0
|
@@ -381,9 +398,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
381
398
|
version: '0'
|
382
399
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
383
400
|
requirements:
|
384
|
-
- - "
|
401
|
+
- - ">="
|
385
402
|
- !ruby/object:Gem::Version
|
386
|
-
version:
|
403
|
+
version: '0'
|
387
404
|
requirements: []
|
388
405
|
rubyforge_project:
|
389
406
|
rubygems_version: 2.6.14
|