splitclient-rb 5.1.4.pre.rc1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -1
- data/CHANGES.txt +7 -2
- data/Detailed-README.md +21 -12
- data/NEWS +4 -3
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +11 -5
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +22 -20
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +29 -51
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +34 -6
- data/lib/splitclient-rb/cache/senders/events_sender.rb +7 -1
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +31 -24
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +5 -3
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +5 -3
- data/lib/splitclient-rb/cache/stores/segment_store.rb +1 -1
- data/lib/splitclient-rb/cache/stores/split_store.rb +7 -1
- data/lib/splitclient-rb/clients/split_client.rb +6 -7
- data/lib/splitclient-rb/engine/api/client.rb +1 -2
- data/lib/splitclient-rb/engine/api/events.rb +13 -12
- data/lib/splitclient-rb/engine/api/impressions.rb +12 -11
- data/lib/splitclient-rb/engine/api/metrics.rb +10 -10
- data/lib/splitclient-rb/engine/parser/evaluator.rb +1 -1
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +16 -21
- data/lib/splitclient-rb/split_config.rb +1 -1
- data/lib/splitclient-rb/split_factory.rb +31 -0
- data/lib/splitclient-rb/validators.rb +27 -23
- data/lib/splitclient-rb/version.rb +1 -1
- data/splitclient-rb.gemspec +1 -3
- metadata +10 -13
- data/exe/splitio +0 -96
- data/splitio.yml.example +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37e343cf9f550bfb1989fc78d36c1bbd19ad1f6e9dc66d31b9eb330866dc5a95
|
4
|
+
data.tar.gz: 9ed27d3f9a249881f7ea73f3862696f93feb71145a3c8a78a8d0a970b1955cea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca9dc9efc7ea8938d22fd3024b3fcb4699815ca8bd9acbd4c00b28e4d7eb3000fcda432e0d631422a9b006295d4f82c101f5d65304b0089a56d7f02e4464f273
|
7
|
+
data.tar.gz: 1640356edd237280e2089d229f651d24e473e146bdfbb13fbec85ad3baa83ea2b5fe3ad6af08a9c7c0d697de7068d2b3ae476f6311243efbafa811b616316edb
|
data/.rubocop.yml
CHANGED
data/CHANGES.txt
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
|
2
|
-
-
|
1
|
+
6.0.0 (December 17th, 2018)
|
2
|
+
- Change `sender` and `store` classes to reuse Faraday connections, preventing issues with net-http-persistent 3.0
|
3
|
+
- Remove producer mode and make `memory + standalone` and `Redis + consumer` the only valid SDK modes. This is a breaking change
|
4
|
+
- Fix `evaluator` bucket calculation when traffic allocation is set to 1%
|
5
|
+
- Change format used to store impressions in repositories to reduce the number of Redis operations
|
6
|
+
- Add cache wrapper to `segments_repository` and `splits_repository` to reduce the number of Redis operations
|
7
|
+
- Add `cache_ttl` and `max_cache_size` options to setup the memory cache wrapper when using redis
|
3
8
|
|
4
9
|
5.1.2 (October 26th, 2018)
|
5
10
|
- Add input validation for client API methods
|
data/Detailed-README.md
CHANGED
@@ -72,6 +72,17 @@ else
|
|
72
72
|
end
|
73
73
|
```
|
74
74
|
|
75
|
+
**Note**: You can ensure the SDK resources are loaded before querying for treatments by using `block_until_ready`. See [Advanced Configuration](#advanced-configuration).
|
76
|
+
``` ruby
|
77
|
+
options = {
|
78
|
+
block_until_ready: 10
|
79
|
+
}
|
80
|
+
|
81
|
+
# Then init the factory passing the options hash
|
82
|
+
factory = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY', options)
|
83
|
+
split_client = factory.client
|
84
|
+
```
|
85
|
+
|
75
86
|
For features that use targeting rules based on user attributes, you can call the `get_treatment` method the following way:
|
76
87
|
|
77
88
|
```ruby
|
@@ -239,7 +250,7 @@ The following values can be customized:
|
|
239
250
|
|
240
251
|
*default value* = `60`
|
241
252
|
|
242
|
-
**impressions_queue_size** : The size of the impressions queue in case of `cache_adapter == :memory`.
|
253
|
+
**impressions_queue_size** : The size of the impressions queue in case of `cache_adapter == :memory`. When the queue is full, existing impressions will be dropped.
|
243
254
|
|
244
255
|
*default value* = 5000
|
245
256
|
|
@@ -247,6 +258,10 @@ The following values can be customized:
|
|
247
258
|
|
248
259
|
*default value* = defaults to `impressions_queue_size`
|
249
260
|
|
261
|
+
**events_queue_size** : The size of the events queue in case of `cache_adapter == :memory`. When the queue is full, existing events will be dropped.
|
262
|
+
|
263
|
+
*default value* = 500
|
264
|
+
|
250
265
|
**debug_enabled** : Enables extra logging (verbose mode).
|
251
266
|
|
252
267
|
*default value* = `false`
|
@@ -329,15 +344,9 @@ options = {
|
|
329
344
|
|
330
345
|
```ruby
|
331
346
|
options = {
|
332
|
-
|
333
|
-
read_timeout: 5,
|
334
|
-
features_refresh_rate: 120,
|
335
|
-
segments_refresh_rate: 120,
|
336
|
-
metrics_refresh_rate: 360,
|
337
|
-
impressions_refresh_rate: 360,
|
338
|
-
logger: Logger.new('logfile.log'),
|
347
|
+
# other options
|
339
348
|
cache_adapter: :redis,
|
340
|
-
mode: :
|
349
|
+
mode: :consumer,
|
341
350
|
redis_url: 'redis://127.0.0.1:6379/0'
|
342
351
|
}
|
343
352
|
begin
|
@@ -388,10 +397,10 @@ In the example above, the listener simply takes an impression and logs it to the
|
|
388
397
|
|
389
398
|
The SDK is capable of running in two different modes to fit in different infrastructure configurations:
|
390
399
|
|
391
|
-
- `:standalone` - (default) : The SDK will retrieve information (e.g. split definitions) periodically from the Split servers, and store it in the
|
392
|
-
- `:consumer` - If using a load balancer or more than one SDK in your application, guaranteeing that all changes in split definitions are picked up by all SDK instances at the same time is highly recommended in order to ensure consistent results across your infrastructure (i.e. getting the same treatment for a specific split and user pair). To achieve this, use the [Split Synchronizer](https://docs.split.io/docs/split-synchronizer)) and setup your SDKs to work in the `consumer` mode. Setting the components this way, all communication with the Split server is orchestrated by the Synchronizer, while the SDKs pick up definitions and store the execution information from / into a shared Redis data store.
|
400
|
+
- `:standalone` - (default) : The SDK will retrieve information (e.g. split definitions) periodically from the Split servers, and store it in the memory cache. It'll also store the application execution information (e.g. impressions) in the cache and send it periodically to the Split servers. As it name implies, in this mode, the SDK neither relies nor synchronizes with any other component. _This mode is only available when using the `memory` cache adapter._
|
401
|
+
- `:consumer` - If using a load balancer or more than one SDK in your application, guaranteeing that all changes in split definitions are picked up by all SDK instances at the same time is highly recommended in order to ensure consistent results across your infrastructure (i.e. getting the same treatment for a specific split and user pair). To achieve this, use the [Split Synchronizer](https://docs.split.io/docs/split-synchronizer)) and setup your SDKs to work in the `consumer` mode. Setting the components this way, all communication with the Split server is orchestrated by the Synchronizer, while the SDKs pick up definitions and store the execution information from / into a shared Redis data store. _This mode is only available when using the `redis` cache adapter._
|
393
402
|
|
394
|
-
_You can choose between these 2 modes setting the `mode` option in the config._
|
403
|
+
_You can choose between these 2 modes setting the `mode` option in the config. An invalid combination of `cache_adaper` and `mode` will result in an Invalid Mode exception being raised._
|
395
404
|
|
396
405
|
## SDK Server Compatibility
|
397
406
|
|
data/NEWS
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
6.0.0
|
2
|
+
Remove producer mode, make memory adapter mandatory in standalone mode, and Redis adapter mandatory in consumer mode. This is a breaking change.
|
3
|
+
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.
|
4
|
+
SDK is now compatible with net-http-persistent 3.0.
|
4
5
|
|
5
6
|
5.1.2
|
6
7
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module SplitIoClient
|
@@ -85,8 +87,8 @@ module SplitIoClient
|
|
85
87
|
end
|
86
88
|
|
87
89
|
# Set
|
88
|
-
|
89
|
-
|
90
|
+
alias initialize_set initialize_map
|
91
|
+
alias find_sets_by_prefix find_strings_by_prefix
|
90
92
|
|
91
93
|
def add_to_set(key, val)
|
92
94
|
@redis.sadd(key, val)
|
@@ -126,7 +128,7 @@ module SplitIoClient
|
|
126
128
|
def get_from_queue(key, count)
|
127
129
|
items = @redis.lrange(key, 0, count - 1)
|
128
130
|
fetched_count = items.size
|
129
|
-
items_to_remove =
|
131
|
+
items_to_remove = fetched_count == count ? count : fetched_count
|
130
132
|
|
131
133
|
@redis.ltrim(key, items_to_remove, -1)
|
132
134
|
|
@@ -148,9 +150,9 @@ module SplitIoClient
|
|
148
150
|
@redis.incrby(key, inc)
|
149
151
|
end
|
150
152
|
|
151
|
-
def pipelined
|
153
|
+
def pipelined
|
152
154
|
@redis.pipelined do
|
153
|
-
|
155
|
+
yield
|
154
156
|
end
|
155
157
|
end
|
156
158
|
|
@@ -159,6 +161,10 @@ module SplitIoClient
|
|
159
161
|
|
160
162
|
keys.map { |key| @redis.del(key) }
|
161
163
|
end
|
164
|
+
|
165
|
+
def expire(key, seconds)
|
166
|
+
@redis.expire(key, seconds)
|
167
|
+
end
|
162
168
|
end
|
163
169
|
end
|
164
170
|
end
|
@@ -1,42 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Repositories
|
4
6
|
module Impressions
|
5
|
-
class MemoryRepository
|
6
|
-
|
7
|
+
class MemoryRepository < ImpressionsRepository
|
7
8
|
def initialize(adapter)
|
8
9
|
@adapter = adapter
|
9
10
|
end
|
10
11
|
|
11
12
|
# Store impression data in the selected adapter
|
12
|
-
def add(split_name,
|
13
|
-
@adapter.add_to_queue(
|
13
|
+
def add(matching_key, bucketing_key, split_name, treatment, time)
|
14
|
+
@adapter.add_to_queue(
|
15
|
+
m: metadata,
|
16
|
+
i: impression_data(
|
17
|
+
matching_key,
|
18
|
+
bucketing_key,
|
19
|
+
split_name,
|
20
|
+
treatment,
|
21
|
+
time
|
22
|
+
)
|
23
|
+
)
|
14
24
|
rescue ThreadError # queue is full
|
15
25
|
if random_sampler.rand(1..1000) <= 2 # log only 0.2 % of the time
|
16
|
-
SplitIoClient.configuration.logger.warn("Dropping impressions. Current size is
|
17
|
-
|
26
|
+
SplitIoClient.configuration.logger.warn("Dropping impressions. Current size is \
|
27
|
+
#{SplitIoClient.configuration.impressions_queue_size}. " \
|
28
|
+
'Consider increasing impressions_queue_size')
|
18
29
|
end
|
19
30
|
end
|
20
31
|
|
21
32
|
def add_bulk(key, bucketing_key, treatments, time)
|
22
33
|
treatments.each do |split_name, treatment|
|
23
|
-
add(
|
24
|
-
split_name,
|
25
|
-
'keyName' => key,
|
26
|
-
'bucketingKey' => bucketing_key,
|
27
|
-
'treatment' => treatment[:treatment],
|
28
|
-
'label' => SplitIoClient.configuration.labels_enabled ? treatment[:label] : nil,
|
29
|
-
'changeNumber' => treatment[:change_number],
|
30
|
-
'time' => time
|
31
|
-
)
|
34
|
+
add(key, bucketing_key, split_name, treatment, time)
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
35
|
-
def
|
36
|
-
return [] if SplitIoClient.configuration.impressions_bulk_size
|
37
|
-
|
38
|
-
|
39
|
-
end
|
38
|
+
def batch
|
39
|
+
return [] if SplitIoClient.configuration.impressions_bulk_size.zero?
|
40
|
+
|
41
|
+
@adapter.get_batch(SplitIoClient.configuration.impressions_bulk_size)
|
40
42
|
end
|
41
43
|
|
42
44
|
private
|
@@ -1,75 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Repositories
|
4
6
|
module Impressions
|
5
|
-
class RedisRepository <
|
7
|
+
class RedisRepository < ImpressionsRepository
|
8
|
+
EXPIRE_SECONDS = 3600
|
6
9
|
|
7
10
|
def initialize(adapter)
|
8
11
|
@adapter = adapter
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
@adapter.add_to_set(
|
14
|
-
impressions_metrics_key("impressions.#{split_name}"),
|
15
|
-
data.to_json
|
16
|
-
)
|
14
|
+
def add(matching_key, bucketing_key, split_name, treatment, time)
|
15
|
+
add_bulk(matching_key, bucketing_key, { split_name => treatment }, time)
|
17
16
|
end
|
18
17
|
|
19
|
-
def add_bulk(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
18
|
+
def add_bulk(matching_key, bucketing_key, treatments, time)
|
19
|
+
impressions = treatments.map do |split_name, treatment|
|
20
|
+
{
|
21
|
+
m: metadata,
|
22
|
+
i: impression_data(
|
23
|
+
matching_key,
|
24
|
+
bucketing_key,
|
25
|
+
split_name,
|
26
|
+
treatment,
|
27
|
+
time
|
28
|
+
)
|
29
|
+
}.to_json
|
30
30
|
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Get random impressions from redis in batches of size SplitIoClient.configuration.impressions_bulk_size,
|
34
|
-
# delete fetched impressions afterwards
|
35
|
-
def get_batch
|
36
|
-
impressions = impression_keys.each_with_object([]) do |key, memo|
|
37
|
-
ip = key.split('/')[-2] # 'prefix/sdk_lang/ip/impressions.name' -> ip
|
38
|
-
if ip.nil?
|
39
|
-
SplitIoClient.configuration.logger.warn("Impressions IP parse error for key: #{key}")
|
40
|
-
next
|
41
|
-
end
|
42
|
-
split_name = key.split('.').last
|
43
|
-
members = @adapter.random_set_elements(key, SplitIoClient.configuration.impressions_bulk_size)
|
44
|
-
members.each do |impression|
|
45
|
-
parsed_impression = JSON.parse(impression)
|
46
31
|
|
47
|
-
|
48
|
-
feature: split_name.to_sym,
|
49
|
-
impressions: parsed_impression,
|
50
|
-
ip: ip
|
51
|
-
}
|
52
|
-
end
|
32
|
+
impressions_list_size = @adapter.add_to_queue(key, impressions)
|
53
33
|
|
54
|
-
|
34
|
+
# Synchronizer might not be running
|
35
|
+
@adapter.expire(key, EXPIRE_SECONDS) if impressions.size == impressions_list_size
|
36
|
+
end
|
55
37
|
|
38
|
+
def batch
|
39
|
+
@adapter.get_from_queue(key, SplitIoClient.configuration.impressions_bulk_size).map do |e|
|
40
|
+
impression = JSON.parse(e, symbolize_names: true)
|
41
|
+
impression[:i][:f] = impression[:i][:f].to_sym
|
42
|
+
impression
|
56
43
|
end
|
57
|
-
impressions
|
58
44
|
rescue StandardError => e
|
59
45
|
SplitIoClient.configuration.logger.error("Exception while clearing impressions cache: #{e}")
|
60
|
-
|
61
46
|
[]
|
62
47
|
end
|
63
48
|
|
64
|
-
|
65
|
-
|
66
|
-
# Get all sets by prefix
|
67
|
-
def impression_keys
|
68
|
-
@adapter.find_sets_by_prefix("#{SplitIoClient.configuration.redis_namespace}/*/impressions.*")
|
69
|
-
rescue StandardError => e
|
70
|
-
SplitIoClient.configuration.logger.error("Exception while fetching impression_keys: #{e}")
|
71
|
-
|
72
|
-
[]
|
49
|
+
def key
|
50
|
+
@key ||= namespace_key('.impressions')
|
73
51
|
end
|
74
52
|
end
|
75
53
|
end
|
@@ -1,18 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Repositories
|
4
6
|
# Repository which forwards impressions interface to the selected adapter
|
5
7
|
class ImpressionsRepository < Repository
|
6
8
|
extend Forwardable
|
7
|
-
def_delegators :@adapter, :add, :add_bulk, :
|
9
|
+
def_delegators :@adapter, :add, :add_bulk, :batch, :empty?
|
8
10
|
|
9
11
|
def initialize(adapter)
|
10
12
|
@adapter = case adapter.class.to_s
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
|
14
|
+
Repositories::Impressions::MemoryRepository.new(adapter)
|
15
|
+
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
16
|
+
Repositories::Impressions::RedisRepository.new(adapter)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def impression_data(matching_key, bucketing_key, split_name, treatment, timestamp)
|
23
|
+
{
|
24
|
+
k: matching_key,
|
25
|
+
b: bucketing_key,
|
26
|
+
f: split_name,
|
27
|
+
t: treatment[:treatment],
|
28
|
+
r: applied_rule(treatment[:label]),
|
29
|
+
c: treatment[:change_number],
|
30
|
+
m: timestamp
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def metadata
|
35
|
+
{
|
36
|
+
s: "#{SplitIoClient.configuration.language}-#{SplitIoClient.configuration.version}",
|
37
|
+
i: SplitIoClient.configuration.machine_ip,
|
38
|
+
n: SplitIoClient.configuration.machine_name
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def applied_rule(label)
|
43
|
+
SplitIoClient.configuration.labels_enabled ? label : nil
|
16
44
|
end
|
17
45
|
end
|
18
46
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Senders
|
@@ -36,10 +38,14 @@ module SplitIoClient
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def post_events
|
39
|
-
|
41
|
+
events_api.post(@events_repository.clear)
|
40
42
|
rescue StandardError => error
|
41
43
|
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
42
44
|
end
|
45
|
+
|
46
|
+
def events_api
|
47
|
+
@events_api ||= SplitIoClient::Api::Events.new(@api_key)
|
48
|
+
end
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Senders
|
@@ -7,29 +9,15 @@ module SplitIoClient
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def call(raw_impressions)
|
10
|
-
impressions = raw_impressions
|
11
|
-
formatted_impressions = []
|
12
|
+
impressions = raw_impressions || @impressions_repository.batch
|
12
13
|
filtered_impressions = filter_impressions(impressions)
|
13
14
|
|
14
15
|
return [] if impressions.empty? || filtered_impressions.empty?
|
15
16
|
|
16
17
|
formatted_impressions = unique_features(filtered_impressions).each_with_object([]) do |feature, memo|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
.select { |impression| impression[:feature] == feature }
|
21
|
-
.map do |impression|
|
22
|
-
ip = impression[:ip]
|
23
|
-
{
|
24
|
-
keyName: impression[:impressions]['keyName'] || impression[:impressions]['key_name'],
|
25
|
-
treatment: impression[:impressions]['treatment'],
|
26
|
-
time: impression[:impressions]['time'],
|
27
|
-
bucketingKey: impression[:impressions]['bucketingKey'] || impression[:impressions]['bucketing_key'],
|
28
|
-
label: impression[:impressions]['label'],
|
29
|
-
changeNumber: impression[:impressions]['changeNumber'] || impression[:impressions]['change_number'],
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
18
|
+
feature_impressions = feature_impressions(filtered_impressions, feature)
|
19
|
+
ip = feature_impressions.first[:m][:i]
|
20
|
+
current_impressions = current_impressions(feature_impressions)
|
33
21
|
memo << {
|
34
22
|
testName: feature.to_sym,
|
35
23
|
keyImpressions: current_impressions,
|
@@ -42,8 +30,27 @@ module SplitIoClient
|
|
42
30
|
|
43
31
|
private
|
44
32
|
|
33
|
+
def feature_impressions(filtered_impressions, feature)
|
34
|
+
filtered_impressions.select do |impression|
|
35
|
+
impression[:i][:f] == feature
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_impressions(feature_impressions)
|
40
|
+
feature_impressions.map do |impression|
|
41
|
+
{
|
42
|
+
keyName: impression[:i][:k],
|
43
|
+
treatment: impression[:i][:t],
|
44
|
+
time: impression[:i][:m],
|
45
|
+
bucketingKey: impression[:i][:b],
|
46
|
+
label: impression[:i][:r],
|
47
|
+
changeNumber: impression[:i][:c]
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
45
52
|
def unique_features(impressions)
|
46
|
-
impressions.map { |impression| impression[:
|
53
|
+
impressions.map { |impression| impression[:i][:f] }.uniq
|
47
54
|
end
|
48
55
|
|
49
56
|
# Filter seen impressions by impression_hash
|
@@ -61,11 +68,11 @@ module SplitIoClient
|
|
61
68
|
end
|
62
69
|
|
63
70
|
def impression_hash(impression)
|
64
|
-
"#{impression[:
|
65
|
-
"#{impression[:
|
66
|
-
"#{impression[:
|
67
|
-
"#{impression[:
|
68
|
-
"#{impression[:
|
71
|
+
"#{impression[:i][:f]}:" \
|
72
|
+
"#{impression[:i][:k]}:" \
|
73
|
+
"#{impression[:i][:b]}:" \
|
74
|
+
"#{impression[:i][:c]}:" \
|
75
|
+
"#{impression[:i][:t]}"
|
69
76
|
end
|
70
77
|
end
|
71
78
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Senders
|
@@ -47,7 +49,7 @@ module SplitIoClient
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def post_impressions
|
50
|
-
|
52
|
+
impressions_api.post(formatted_impressions)
|
51
53
|
rescue StandardError => error
|
52
54
|
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
53
55
|
end
|
@@ -56,8 +58,8 @@ module SplitIoClient
|
|
56
58
|
ImpressionsFormatter.new(@impressions_repository).call(raw_impressions)
|
57
59
|
end
|
58
60
|
|
59
|
-
def
|
60
|
-
SplitIoClient::Api::Impressions.new(@api_key
|
61
|
+
def impressions_api
|
62
|
+
@impressions_api ||= SplitIoClient::Api::Impressions.new(@api_key)
|
61
63
|
end
|
62
64
|
end
|
63
65
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Senders
|
@@ -34,13 +36,13 @@ module SplitIoClient
|
|
34
36
|
end
|
35
37
|
|
36
38
|
def post_metrics
|
37
|
-
|
39
|
+
metrics_api.post
|
38
40
|
rescue StandardError => error
|
39
41
|
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
40
42
|
end
|
41
43
|
|
42
|
-
def
|
43
|
-
SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository)
|
44
|
+
def metrics_api
|
45
|
+
@metrics_api ||= SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
@@ -66,7 +66,7 @@ module SplitIoClient
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def splits_since(since)
|
69
|
-
|
69
|
+
splits_api.since(since)
|
70
70
|
end
|
71
71
|
|
72
72
|
def add_split_unless_archived(split)
|
@@ -90,6 +90,12 @@ module SplitIoClient
|
|
90
90
|
|
91
91
|
@splits_repository.add_split(split)
|
92
92
|
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def splits_api
|
97
|
+
@splits_api ||= SplitIoClient::Api::Splits.new(@api_key, @metrics)
|
98
|
+
end
|
93
99
|
end
|
94
100
|
end
|
95
101
|
end
|
@@ -136,13 +136,12 @@ module SplitIoClient
|
|
136
136
|
|
137
137
|
return if SplitIoClient.configuration.disable_impressions || !store_impressions
|
138
138
|
|
139
|
-
@impressions_repository.add(
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
'changeNumber' => treatment[:change_number]
|
139
|
+
@impressions_repository.add(
|
140
|
+
matching_key,
|
141
|
+
bucketing_key,
|
142
|
+
split_name,
|
143
|
+
treatment,
|
144
|
+
time
|
146
145
|
)
|
147
146
|
|
148
147
|
route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
|
@@ -38,8 +38,7 @@ module SplitIoClient
|
|
38
38
|
end
|
39
39
|
rescue StandardError => e
|
40
40
|
SplitIoClient.configuration.logger.warn("#{e}\nURL:#{url}\ndata:#{data}\nparams:#{params}")
|
41
|
-
|
42
|
-
false
|
41
|
+
raise 'Split SDK failed to connect to backend to retrieve information'
|
43
42
|
end
|
44
43
|
|
45
44
|
private
|
@@ -1,31 +1,32 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
module Api
|
3
3
|
class Events < Client
|
4
|
-
def initialize(api_key
|
4
|
+
def initialize(api_key)
|
5
5
|
@api_key = api_key
|
6
|
-
@events = events
|
7
6
|
end
|
8
7
|
|
9
|
-
def post
|
10
|
-
if
|
8
|
+
def post(events)
|
9
|
+
if events.empty?
|
11
10
|
SplitIoClient.configuration.logger.debug('No events to report') if SplitIoClient.configuration.debug_enabled
|
12
11
|
return
|
13
12
|
end
|
14
13
|
|
15
|
-
|
14
|
+
events.each_slice(SplitIoClient.configuration.events_queue_size) do |events_slice|
|
16
15
|
result = post_api(
|
17
16
|
"#{SplitIoClient.configuration.events_uri}/events/bulk",
|
18
17
|
@api_key,
|
19
|
-
|
20
|
-
'SplitSDKMachineIP' =>
|
21
|
-
'SplitSDKMachineName' =>
|
22
|
-
'SplitSDKVersion' =>
|
18
|
+
events_slice.map { |event| formatted_event(event[:e]) },
|
19
|
+
'SplitSDKMachineIP' => events_slice[0][:m][:i],
|
20
|
+
'SplitSDKMachineName' => events_slice[0][:m][:n],
|
21
|
+
'SplitSDKVersion' => events_slice[0][:m][:s]
|
23
22
|
)
|
24
23
|
|
25
|
-
if
|
26
|
-
|
24
|
+
if response.success?
|
25
|
+
SplitLogger.log_if_debug("Events reported: #{events_slice.size}")
|
27
26
|
else
|
28
|
-
|
27
|
+
SplitLogger.log_error("Unexpected status code while posting events: #{response.status}." \
|
28
|
+
" - Check your API key and base URI")
|
29
|
+
raise 'Split SDK failed to connect to backend to post events'
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -1,24 +1,25 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
module Api
|
3
3
|
class Impressions < Client
|
4
|
-
def initialize(api_key
|
4
|
+
def initialize(api_key)
|
5
5
|
@api_key = api_key
|
6
|
-
@impressions = impressions
|
7
6
|
end
|
8
7
|
|
9
|
-
def post
|
10
|
-
if
|
8
|
+
def post(impressions)
|
9
|
+
if impressions.empty?
|
11
10
|
SplitIoClient.configuration.logger.debug('No impressions to report') if SplitIoClient.configuration.debug_enabled
|
12
11
|
return
|
13
12
|
end
|
14
13
|
|
15
|
-
impressions_by_ip.each do |ip,
|
16
|
-
result = post_api("#{SplitIoClient.configuration.events_uri}/testImpressions/bulk", @api_key,
|
14
|
+
impressions_by_ip(impressions).each do |ip, impressions_ip|
|
15
|
+
result = post_api("#{SplitIoClient.configuration.events_uri}/testImpressions/bulk", @api_key, impressions_ip, 'SplitSDKMachineIP' => ip)
|
17
16
|
|
18
|
-
if
|
19
|
-
|
17
|
+
if response.success?
|
18
|
+
SplitLogger.log_if_debug("Impressions reported: #{total_impressions(impressions)}")
|
20
19
|
else
|
21
|
-
|
20
|
+
SplitLogger.log_error("Unexpected status code while posting impressions: #{response.status}." \
|
21
|
+
" - Check your API key and base URI")
|
22
|
+
raise 'Split SDK failed to connect to backend to post impressions'
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -33,8 +34,8 @@ module SplitIoClient
|
|
33
34
|
|
34
35
|
private
|
35
36
|
|
36
|
-
def impressions_by_ip
|
37
|
-
|
37
|
+
def impressions_by_ip(impressions)
|
38
|
+
impressions.group_by { |impression| impression[:ip] }
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -20,9 +20,9 @@ module SplitIoClient
|
|
20
20
|
@metrics_repository.latencies.each do |name, latencies|
|
21
21
|
metrics_time = { name: name, latencies: latencies }
|
22
22
|
|
23
|
-
|
23
|
+
response = post_api("#{SplitIoClient.configuration.events_uri}/metrics/time", @api_key, metrics_time)
|
24
24
|
|
25
|
-
log_status(
|
25
|
+
log_status(response, metrics_time.size)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -36,9 +36,9 @@ module SplitIoClient
|
|
36
36
|
@metrics_repository.counts.each do |name, count|
|
37
37
|
metrics_count = { name: name, delta: count }
|
38
38
|
|
39
|
-
|
39
|
+
response = post_api("#{SplitIoClient.configuration.events_uri}/metrics/counter", @api_key, metrics_count)
|
40
40
|
|
41
|
-
log_status(
|
41
|
+
log_status(response, metrics_count.size)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
@metrics_repository.clear_counts
|
@@ -46,13 +46,13 @@ module SplitIoClient
|
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
|
-
def log_status(
|
50
|
-
if
|
51
|
-
|
52
|
-
elsif (200..299).include? result.status
|
53
|
-
SplitIoClient.configuration.logger.debug("Metric time reported: #{info_to_log}") if SplitIoClient.configuration.debug_enabled
|
49
|
+
def log_status(response, info_to_log)
|
50
|
+
if response.success?
|
51
|
+
SplitLogger.log_if_debug("Metric time reported: #{info_to_log}")
|
54
52
|
else
|
55
|
-
|
53
|
+
SplitLogger.log_error("Unexpected status code while posting time metrics: #{response.status}" \
|
54
|
+
" - Check your API key and base URI")
|
55
|
+
raise 'Split SDK failed to connect to backend to post metrics'
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -51,7 +51,7 @@ module SplitIoClient
|
|
51
51
|
if split[:trafficAllocation] < 100
|
52
52
|
bucket = splitter.bucket(splitter.count_hash(key, split[:trafficAllocationSeed].to_i, legacy_algo))
|
53
53
|
|
54
|
-
if bucket
|
54
|
+
if bucket > split[:trafficAllocation]
|
55
55
|
return treatment_hash(Models::Label::NOT_IN_SPLIT, split[:defaultTreatment], split[:changeNumber])
|
56
56
|
end
|
57
57
|
end
|
@@ -24,7 +24,15 @@ module SplitIoClient
|
|
24
24
|
# @param sdk_blocker [SDKBlocker] SDKBlocker instance which blocks splits_repository/segments_repository
|
25
25
|
#
|
26
26
|
# @return [SplitIoClient] split.io client instance
|
27
|
-
def initialize(
|
27
|
+
def initialize(
|
28
|
+
api_key,
|
29
|
+
splits_repository,
|
30
|
+
segments_repository,
|
31
|
+
impressions_repository,
|
32
|
+
metrics_repository,
|
33
|
+
events_repository,
|
34
|
+
sdk_blocker
|
35
|
+
)
|
28
36
|
@api_key = api_key
|
29
37
|
@splits_repository = splits_repository
|
30
38
|
@segments_repository = segments_repository
|
@@ -34,28 +42,15 @@ module SplitIoClient
|
|
34
42
|
@metrics = Metrics.new(100, @metrics_repository)
|
35
43
|
@sdk_blocker = sdk_blocker
|
36
44
|
|
37
|
-
|
45
|
+
start_standalone_components if SplitIoClient.configuration.mode == :standalone
|
38
46
|
end
|
39
47
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
impressions_sender
|
47
|
-
events_sender
|
48
|
-
when :consumer
|
49
|
-
# Do nothing in background
|
50
|
-
when :producer
|
51
|
-
split_store
|
52
|
-
segment_store
|
53
|
-
impressions_sender
|
54
|
-
metrics_sender
|
55
|
-
events_sender
|
56
|
-
|
57
|
-
sleep unless ENV['SPLITCLIENT_ENV'] == 'test'
|
58
|
-
end
|
48
|
+
def start_standalone_components
|
49
|
+
split_store
|
50
|
+
segment_store
|
51
|
+
metrics_sender
|
52
|
+
impressions_sender
|
53
|
+
events_sender
|
59
54
|
end
|
60
55
|
|
61
56
|
# Starts thread which loops constantly and stores splits in the splits_repository of choice
|
@@ -109,7 +109,7 @@ module SplitIoClient
|
|
109
109
|
#
|
110
110
|
# The mode SDK will run
|
111
111
|
#
|
112
|
-
# @return [Symbol] One of the available SDK modes: standalone, consumer
|
112
|
+
# @return [Symbol] One of the available SDK modes: standalone, consumer
|
113
113
|
attr_accessor :mode
|
114
114
|
|
115
115
|
# The read timeout for network connections in seconds.
|
@@ -8,6 +8,9 @@ module SplitIoClient
|
|
8
8
|
def initialize(api_key, config_hash = {})
|
9
9
|
@api_key = api_key
|
10
10
|
SplitIoClient.configure(config_hash)
|
11
|
+
|
12
|
+
raise 'Invalid SDK mode' unless valid_mode
|
13
|
+
|
11
14
|
@cache_adapter = SplitIoClient.configuration.cache_adapter
|
12
15
|
|
13
16
|
@splits_repository = SplitsRepository.new(@cache_adapter)
|
@@ -33,6 +36,34 @@ module SplitIoClient
|
|
33
36
|
SplitIoClient.configuration.threads.each { |_, t| t.exit }
|
34
37
|
end
|
35
38
|
|
39
|
+
def valid_mode
|
40
|
+
valid_startup_mode = false
|
41
|
+
case SplitIoClient.configuration.mode
|
42
|
+
when :consumer
|
43
|
+
if SplitIoClient.configuration.cache_adapter.is_a? SplitIoClient::Cache::Adapters::RedisAdapter
|
44
|
+
valid_startup_mode = true
|
45
|
+
else
|
46
|
+
SplitIoClient.configuration.logger.error('Consumer mode cannot be used with Memory adapter. ' \
|
47
|
+
'Use Redis adapter instead.')
|
48
|
+
end
|
49
|
+
when :standalone
|
50
|
+
if SplitIoClient.configuration.cache_adapter.is_a? SplitIoClient::Cache::Adapters::MemoryAdapter
|
51
|
+
valid_startup_mode = true
|
52
|
+
else
|
53
|
+
SplitIoClient.configuration.logger.error('Standalone mode cannot be used with Redis adapter. ' \
|
54
|
+
'Use Memory adapter instead.')
|
55
|
+
end
|
56
|
+
when :producer
|
57
|
+
SplitIoClient.configuration.logger.error('Producer mode is no longer supported. Use Split Synchronizer. ' \
|
58
|
+
'See: https://github.com/splitio/split-synchronizer')
|
59
|
+
else
|
60
|
+
SplitIoClient.configuration.logger.error('Invalid SDK mode selected. ' \
|
61
|
+
"Valid modes are 'standalone with memory adapter' and 'consumer with redis adapter'")
|
62
|
+
end
|
63
|
+
|
64
|
+
valid_startup_mode
|
65
|
+
end
|
66
|
+
|
36
67
|
alias resume! start!
|
37
68
|
end
|
38
69
|
end
|
@@ -1,9 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Validators
|
3
5
|
extend self
|
4
6
|
|
5
7
|
def valid_get_treatment_parameters(key, split_name, matching_key, bucketing_key)
|
6
|
-
valid_key?(key) &&
|
8
|
+
valid_key?(key) &&
|
9
|
+
valid_split_name?(split_name) &&
|
10
|
+
valid_matching_key?(matching_key) &&
|
11
|
+
valid_bucketing_key?(key, bucketing_key)
|
7
12
|
end
|
8
13
|
|
9
14
|
def valid_get_treatments_parameters(split_names)
|
@@ -11,7 +16,10 @@ module SplitIoClient
|
|
11
16
|
end
|
12
17
|
|
13
18
|
def valid_track_parameters(key, traffic_type_name, event_type, value)
|
14
|
-
valid_track_key?(key) &&
|
19
|
+
valid_track_key?(key) &&
|
20
|
+
valid_traffic_type_name?(traffic_type_name) &&
|
21
|
+
valid_event_type?(event_type) &&
|
22
|
+
valid_value?(value)
|
15
23
|
end
|
16
24
|
|
17
25
|
def valid_split_parameters(split_name)
|
@@ -44,7 +52,7 @@ module SplitIoClient
|
|
44
52
|
SplitIoClient.configuration.logger.warn("#{method}: #{key} is not of type String, converting to String")
|
45
53
|
end
|
46
54
|
|
47
|
-
def valid_split_name?(split_name, method
|
55
|
+
def valid_split_name?(split_name, method = :get_treatment)
|
48
56
|
if split_name.nil?
|
49
57
|
log_nil(:split_name, method)
|
50
58
|
return false
|
@@ -55,7 +63,7 @@ module SplitIoClient
|
|
55
63
|
return false
|
56
64
|
end
|
57
65
|
|
58
|
-
|
66
|
+
true
|
59
67
|
end
|
60
68
|
|
61
69
|
def valid_key?(key)
|
@@ -64,7 +72,7 @@ module SplitIoClient
|
|
64
72
|
return false
|
65
73
|
end
|
66
74
|
|
67
|
-
|
75
|
+
true
|
68
76
|
end
|
69
77
|
|
70
78
|
def valid_matching_key?(matching_key)
|
@@ -78,16 +86,16 @@ module SplitIoClient
|
|
78
86
|
return false
|
79
87
|
end
|
80
88
|
|
81
|
-
if matching_key.is_a? Numeric
|
82
|
-
log_convert_numeric(:matching_key, :get_treatment)
|
83
|
-
end
|
89
|
+
log_convert_numeric(:matching_key, :get_treatment) if matching_key.is_a? Numeric
|
84
90
|
|
85
|
-
|
91
|
+
true
|
86
92
|
end
|
87
93
|
|
88
|
-
def valid_bucketing_key?(bucketing_key)
|
94
|
+
def valid_bucketing_key?(key, bucketing_key)
|
89
95
|
if bucketing_key.nil?
|
90
|
-
|
96
|
+
if key.is_a? Hash
|
97
|
+
SplitIoClient.configuration.logger.warn('get_treatment: key object should have bucketing_key set')
|
98
|
+
end
|
91
99
|
return true
|
92
100
|
end
|
93
101
|
|
@@ -96,11 +104,9 @@ module SplitIoClient
|
|
96
104
|
return false
|
97
105
|
end
|
98
106
|
|
99
|
-
if bucketing_key.is_a? Numeric
|
100
|
-
log_convert_numeric(:bucketing_key, :get_treatment)
|
101
|
-
end
|
107
|
+
log_convert_numeric(:bucketing_key, :get_treatment) if bucketing_key.is_a? Numeric
|
102
108
|
|
103
|
-
|
109
|
+
true
|
104
110
|
end
|
105
111
|
|
106
112
|
def valid_split_names?(split_names)
|
@@ -114,7 +120,7 @@ module SplitIoClient
|
|
114
120
|
return false
|
115
121
|
end
|
116
122
|
|
117
|
-
|
123
|
+
true
|
118
124
|
end
|
119
125
|
|
120
126
|
def valid_track_key?(key)
|
@@ -128,11 +134,9 @@ module SplitIoClient
|
|
128
134
|
return false
|
129
135
|
end
|
130
136
|
|
131
|
-
if key.is_a? Numeric
|
132
|
-
log_convert_numeric(:key, :track)
|
133
|
-
end
|
137
|
+
log_convert_numeric(:key, :track) if key.is_a? Numeric
|
134
138
|
|
135
|
-
|
139
|
+
true
|
136
140
|
end
|
137
141
|
|
138
142
|
def valid_event_type?(event_type)
|
@@ -151,7 +155,7 @@ module SplitIoClient
|
|
151
155
|
return false
|
152
156
|
end
|
153
157
|
|
154
|
-
|
158
|
+
true
|
155
159
|
end
|
156
160
|
|
157
161
|
def valid_traffic_type_name?(traffic_type_name)
|
@@ -170,7 +174,7 @@ module SplitIoClient
|
|
170
174
|
return false
|
171
175
|
end
|
172
176
|
|
173
|
-
|
177
|
+
true
|
174
178
|
end
|
175
179
|
|
176
180
|
def valid_value?(value)
|
@@ -179,7 +183,7 @@ module SplitIoClient
|
|
179
183
|
return false
|
180
184
|
end
|
181
185
|
|
182
|
-
|
186
|
+
true
|
183
187
|
end
|
184
188
|
end
|
185
189
|
end
|
data/splitclient-rb.gemspec
CHANGED
@@ -17,8 +17,6 @@ Gem::Specification.new do |spec|
|
|
17
17
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|features|ext)/}) }
|
19
19
|
|
20
|
-
spec.bindir = 'exe'
|
21
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
20
|
spec.require_paths = ['lib']
|
23
21
|
|
24
22
|
if defined?(JRUBY_VERSION)
|
@@ -53,7 +51,7 @@ Gem::Specification.new do |spec|
|
|
53
51
|
spec.add_runtime_dependency 'faraday', '>= 0.8'
|
54
52
|
spec.add_runtime_dependency 'json', '>= 1.8'
|
55
53
|
spec.add_runtime_dependency 'lru_redux'
|
56
|
-
spec.add_runtime_dependency 'net-http-persistent', '
|
54
|
+
spec.add_runtime_dependency 'net-http-persistent', '>= 2.9'
|
57
55
|
spec.add_runtime_dependency 'redis', '>= 3.2'
|
58
56
|
spec.add_runtime_dependency 'thread_safe', '>= 0.3'
|
59
57
|
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:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: allocation_stats
|
@@ -224,16 +224,16 @@ dependencies:
|
|
224
224
|
name: net-http-persistent
|
225
225
|
requirement: !ruby/object:Gem::Requirement
|
226
226
|
requirements:
|
227
|
-
- - "
|
227
|
+
- - ">="
|
228
228
|
- !ruby/object:Gem::Version
|
229
|
-
version: '
|
229
|
+
version: '2.9'
|
230
230
|
type: :runtime
|
231
231
|
prerelease: false
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
233
233
|
requirements:
|
234
|
-
- - "
|
234
|
+
- - ">="
|
235
235
|
- !ruby/object:Gem::Version
|
236
|
-
version: '
|
236
|
+
version: '2.9'
|
237
237
|
- !ruby/object:Gem::Dependency
|
238
238
|
name: redis
|
239
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -265,8 +265,7 @@ dependencies:
|
|
265
265
|
description: Ruby client for using split SDK.
|
266
266
|
email:
|
267
267
|
- pato@split.io
|
268
|
-
executables:
|
269
|
-
- splitio
|
268
|
+
executables: []
|
270
269
|
extensions:
|
271
270
|
- ext/murmurhash/extconf.rb
|
272
271
|
extra_rdoc_files: []
|
@@ -280,7 +279,6 @@ files:
|
|
280
279
|
- NEWS
|
281
280
|
- README.md
|
282
281
|
- Rakefile
|
283
|
-
- exe/splitio
|
284
282
|
- ext/murmurhash/3_x86_32.c
|
285
283
|
- ext/murmurhash/extconf.rb
|
286
284
|
- ext/murmurhash/murmurhash.c
|
@@ -367,7 +365,6 @@ files:
|
|
367
365
|
- lib/splitclient-rb/validators.rb
|
368
366
|
- lib/splitclient-rb/version.rb
|
369
367
|
- splitclient-rb.gemspec
|
370
|
-
- splitio.yml.example
|
371
368
|
- tasks/benchmark_get_treatment.rake
|
372
369
|
- tasks/irb.rake
|
373
370
|
- tasks/rspec.rake
|
@@ -386,9 +383,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
386
383
|
version: '0'
|
387
384
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
388
385
|
requirements:
|
389
|
-
- - "
|
386
|
+
- - ">="
|
390
387
|
- !ruby/object:Gem::Version
|
391
|
-
version:
|
388
|
+
version: '0'
|
392
389
|
requirements: []
|
393
390
|
rubyforge_project:
|
394
391
|
rubygems_version: 2.7.6
|
data/exe/splitio
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
lib = File.expand_path('../lib', __dir__)
|
5
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
-
|
7
|
-
require 'optparse'
|
8
|
-
require 'yaml'
|
9
|
-
require_relative '../lib/splitclient-rb'
|
10
|
-
|
11
|
-
# ARGV << '-h' if ARGV.empty?
|
12
|
-
|
13
|
-
config_path = ''
|
14
|
-
options = {}
|
15
|
-
opt_parser = OptionParser.new do |opts|
|
16
|
-
opts.banner = 'Usage: splitio [options]'
|
17
|
-
|
18
|
-
opts.on('-cPATH', '--config=PATH', 'Set the path to splitio.yml config file') do |c|
|
19
|
-
config_path = c
|
20
|
-
end
|
21
|
-
|
22
|
-
opts.on('--base-uri=BASE_URI', 'Set the base uri for Split SDK') do |c|
|
23
|
-
options[:base_uri] = c
|
24
|
-
end
|
25
|
-
|
26
|
-
opts.on('--events-uri=EVENTS_URI', 'Set the events uri for Split SDK') do |c|
|
27
|
-
options[:events_uri] = c
|
28
|
-
end
|
29
|
-
|
30
|
-
opts.on('--api-key=API_KEY', 'Set the API Key for Split SDK') do |c|
|
31
|
-
options[:api_key] = c
|
32
|
-
end
|
33
|
-
|
34
|
-
opts.on('--read-timeout=READ_TIMEOUT', 'Read timeout in seconds') do |c|
|
35
|
-
options[:read_timeout] = c
|
36
|
-
end
|
37
|
-
|
38
|
-
opts.on('--connection-timeout=CONNECTION_TIMEOUT', 'Connection timeout in seconds') do |c|
|
39
|
-
options[:connection_timeout] = c
|
40
|
-
end
|
41
|
-
|
42
|
-
opts.on('--features-refresh-rate=FEATURES_REFRESH_RATE', 'Features refresh rate in seconds') do |c|
|
43
|
-
options[:features_refresh_rate] = c
|
44
|
-
end
|
45
|
-
|
46
|
-
opts.on('--segments-refresh-rate=SEGMENTS_REFRESH_RATE', 'Segments refresh rate in seconds') do |c|
|
47
|
-
options[:segments_refresh_rate] = c
|
48
|
-
end
|
49
|
-
|
50
|
-
opts.on('--metrics-refresh-rate=METRICS_REFRESH_RATE', 'Metrics refresh rate in seconds') do |c|
|
51
|
-
options[:metrics_refresh_rate] = c
|
52
|
-
end
|
53
|
-
|
54
|
-
opts.on('--impressions-refresh-rate=IMPRESSIONS_REFRESH_RATE', 'Impressions refresh rate in seconds') do |c|
|
55
|
-
options[:impressions_refresh_rate] = c
|
56
|
-
end
|
57
|
-
|
58
|
-
opts.on('--ready=SECONDS', 'Seconds to block the app until SDK is ready or false to run in non-blocking mode') do |c|
|
59
|
-
options[:ready] = c
|
60
|
-
end
|
61
|
-
|
62
|
-
opts.on('--redis-url=REDIS_URL', 'Set base uri for Split SDK') do |c|
|
63
|
-
options[:redis_url] = c
|
64
|
-
end
|
65
|
-
|
66
|
-
opts.on('--transport-debug', 'Enable transport debug') do
|
67
|
-
options[:transport_debug_enabled] = true
|
68
|
-
end
|
69
|
-
|
70
|
-
opts.on('-d', '--debug', 'Enable debug mode') do
|
71
|
-
options[:debug_enabled] = true
|
72
|
-
end
|
73
|
-
|
74
|
-
opts.on_tail('-h', '--help', 'Prints this help') do
|
75
|
-
puts opts
|
76
|
-
exit
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
begin
|
81
|
-
opt_parser.parse!(ARGV)
|
82
|
-
rescue OptionParser::InvalidOption => e
|
83
|
-
puts e
|
84
|
-
puts opt_parser
|
85
|
-
exit(1)
|
86
|
-
end
|
87
|
-
|
88
|
-
config = config_path != '' ? YAML.load_file(config_path) : {}
|
89
|
-
config
|
90
|
-
.merge!(mode: :producer, cache_adapter: :redis)
|
91
|
-
.merge!(options)
|
92
|
-
.merge!(api_key: ENV['API_KEY'] || config[:api_key])
|
93
|
-
.merge!(base_uri: ENV['SDK_URI'] || config[:base_uri])[:events_uri] = ENV['EVENTS_URI'] || config[:events_uri]
|
94
|
-
# IDENTIFY_BASE_URI
|
95
|
-
|
96
|
-
SplitIoClient::SplitFactory.new(config[:api_key], config)
|