splitclient-rb 5.0.3.pre.rc1-java → 5.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -0
- data/CHANGES.txt +8 -1
- data/Detailed-README.md +246 -313
- data/Gemfile +2 -0
- data/NEWS +12 -2
- data/Rakefile +6 -2
- data/exe/splitio +20 -20
- data/lib/splitclient-rb.rb +1 -0
- data/lib/splitclient-rb/engine/api/client.rb +1 -2
- data/lib/splitclient-rb/engine/api/segments.rb +33 -27
- data/lib/splitclient-rb/engine/api/splits.rb +22 -17
- data/lib/splitclient-rb/split_config.rb +1 -1
- data/lib/splitclient-rb/split_logger.rb +29 -0
- data/lib/splitclient-rb/version.rb +1 -1
- data/splitclient-rb.gemspec +38 -34
- data/tasks/benchmark_get_treatment.rake +31 -17
- data/tasks/irb.rake +5 -3
- data/tasks/rspec.rake +3 -1
- metadata +69 -25
data/Gemfile
CHANGED
data/NEWS
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
5.1.0
|
2
|
+
|
3
|
+
Prevent unhandled exceptions from raising when API get calls fail on Segments and Treatments.
|
4
|
+
|
5
|
+
5.0.3
|
6
|
+
|
7
|
+
Creates a new configuration parameter (impressions_bulk_size) to manage the max number of impressions sent to the Split backend on each post.
|
8
|
+
Changes impressions_queue_size so that it manages only the queue size in the memory adapter.
|
9
|
+
A backwards compatibility fail safe is included for users of previous SDK versions.
|
10
|
+
|
1
11
|
5.0.2
|
2
12
|
|
3
13
|
Turn Impression Listener into an optional SDK feature.
|
@@ -5,13 +15,13 @@ Prevents the impression thread from being started if a listener is not in place
|
|
5
15
|
|
6
16
|
5.0.1
|
7
17
|
|
8
|
-
Adding stop! method to the factory.
|
18
|
+
Adding stop! method to the factory.
|
9
19
|
With this method the user will be able to stop the threads that queries the Split Service. This will be used in the before_fork configuration in Puma and Unicorn to stop the threads in the master process.
|
10
20
|
|
11
21
|
5.0.0
|
12
22
|
|
13
23
|
This is a breaking change in how users buckets are allocated.
|
14
|
-
Ruby SDK was wrongly picking up the right buckets and defauled to
|
24
|
+
Ruby SDK was wrongly picking up the right buckets and defauled to
|
15
25
|
use a "legacy hashing" instead of our moder murmur3 algo which is
|
16
26
|
what other SDKs use. Please reach out to support@split.io for help
|
17
27
|
on how to upgrade to this release.
|
data/Rakefile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
3
6
|
|
4
7
|
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
5
8
|
|
6
9
|
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
RuboCop::RakeTask.new(:rubocop)
|
7
11
|
|
8
|
-
task :
|
12
|
+
task spec: :compile
|
9
13
|
case RUBY_PLATFORM
|
10
14
|
when 'java'
|
11
15
|
require 'rake/javaextensiontask'
|
@@ -21,4 +25,4 @@ else
|
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
task :
|
28
|
+
task default: %i[spec rubocop]
|
data/exe/splitio
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
lib = File.expand_path('
|
4
|
+
lib = File.expand_path('../lib', __dir__)
|
4
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
6
|
|
6
7
|
require 'optparse'
|
@@ -12,65 +13,65 @@ require_relative '../lib/splitclient-rb'
|
|
12
13
|
config_path = ''
|
13
14
|
options = {}
|
14
15
|
opt_parser = OptionParser.new do |opts|
|
15
|
-
opts.banner =
|
16
|
+
opts.banner = 'Usage: splitio [options]'
|
16
17
|
|
17
|
-
opts.on(
|
18
|
+
opts.on('-cPATH', '--config=PATH', 'Set the path to splitio.yml config file') do |c|
|
18
19
|
config_path = c
|
19
20
|
end
|
20
21
|
|
21
|
-
opts.on(
|
22
|
+
opts.on('--base-uri=BASE_URI', 'Set the base uri for Split SDK') do |c|
|
22
23
|
options[:base_uri] = c
|
23
24
|
end
|
24
25
|
|
25
|
-
opts.on(
|
26
|
+
opts.on('--events-uri=EVENTS_URI', 'Set the events uri for Split SDK') do |c|
|
26
27
|
options[:events_uri] = c
|
27
28
|
end
|
28
29
|
|
29
|
-
opts.on(
|
30
|
+
opts.on('--api-key=API_KEY', 'Set the API Key for Split SDK') do |c|
|
30
31
|
options[:api_key] = c
|
31
32
|
end
|
32
33
|
|
33
|
-
opts.on(
|
34
|
+
opts.on('--read-timeout=READ_TIMEOUT', 'Read timeout in seconds') do |c|
|
34
35
|
options[:read_timeout] = c
|
35
36
|
end
|
36
37
|
|
37
|
-
opts.on(
|
38
|
+
opts.on('--connection-timeout=CONNECTION_TIMEOUT', 'Connection timeout in seconds') do |c|
|
38
39
|
options[:connection_timeout] = c
|
39
40
|
end
|
40
41
|
|
41
|
-
opts.on(
|
42
|
+
opts.on('--features-refresh-rate=FEATURES_REFRESH_RATE', 'Features refresh rate in seconds') do |c|
|
42
43
|
options[:features_refresh_rate] = c
|
43
44
|
end
|
44
45
|
|
45
|
-
opts.on(
|
46
|
+
opts.on('--segments-refresh-rate=SEGMENTS_REFRESH_RATE', 'Segments refresh rate in seconds') do |c|
|
46
47
|
options[:segments_refresh_rate] = c
|
47
48
|
end
|
48
49
|
|
49
|
-
opts.on(
|
50
|
+
opts.on('--metrics-refresh-rate=METRICS_REFRESH_RATE', 'Metrics refresh rate in seconds') do |c|
|
50
51
|
options[:metrics_refresh_rate] = c
|
51
52
|
end
|
52
53
|
|
53
|
-
opts.on(
|
54
|
+
opts.on('--impressions-refresh-rate=IMPRESSIONS_REFRESH_RATE', 'Impressions refresh rate in seconds') do |c|
|
54
55
|
options[:impressions_refresh_rate] = c
|
55
56
|
end
|
56
57
|
|
57
|
-
opts.on(
|
58
|
+
opts.on('--ready=SECONDS', 'Seconds to block the app until SDK is ready or false to run in non-blocking mode') do |c|
|
58
59
|
options[:ready] = c
|
59
60
|
end
|
60
61
|
|
61
|
-
opts.on(
|
62
|
+
opts.on('--redis-url=REDIS_URL', 'Set base uri for Split SDK') do |c|
|
62
63
|
options[:redis_url] = c
|
63
64
|
end
|
64
65
|
|
65
|
-
opts.on(
|
66
|
+
opts.on('--transport-debug', 'Enable transport debug') do
|
66
67
|
options[:transport_debug_enabled] = true
|
67
68
|
end
|
68
69
|
|
69
|
-
opts.on(
|
70
|
+
opts.on('-d', '--debug', 'Enable debug mode') do
|
70
71
|
options[:debug_enabled] = true
|
71
72
|
end
|
72
73
|
|
73
|
-
opts.on_tail(
|
74
|
+
opts.on_tail('-h', '--help', 'Prints this help') do
|
74
75
|
puts opts
|
75
76
|
exit
|
76
77
|
end
|
@@ -89,8 +90,7 @@ config
|
|
89
90
|
.merge!(mode: :producer, cache_adapter: :redis)
|
90
91
|
.merge!(options)
|
91
92
|
.merge!(api_key: ENV['API_KEY'] || config[:api_key])
|
92
|
-
.merge!(base_uri: ENV['SDK_URI'] || config[:base_uri])
|
93
|
-
|
94
|
-
# IDENTIFY_BASE_URI
|
93
|
+
.merge!(base_uri: ENV['SDK_URI'] || config[:base_uri])[:events_uri] = ENV['EVENTS_URI'] || config[:events_uri]
|
94
|
+
# IDENTIFY_BASE_URI
|
95
95
|
|
96
96
|
SplitIoClient::SplitFactory.new(config[:api_key], config)
|
data/lib/splitclient-rb.rb
CHANGED
@@ -38,6 +38,7 @@ require 'splitclient-rb/split_factory'
|
|
38
38
|
require 'splitclient-rb/split_factory_builder'
|
39
39
|
require 'splitclient-rb/localhost_split_factory'
|
40
40
|
require 'splitclient-rb/split_config'
|
41
|
+
require 'splitclient-rb/split_logger'
|
41
42
|
|
42
43
|
require 'splitclient-rb/engine/api/faraday_middleware/gzip'
|
43
44
|
require 'splitclient-rb/engine/api/client'
|
@@ -16,8 +16,7 @@ module SplitIoClient
|
|
16
16
|
end
|
17
17
|
rescue StandardError => e
|
18
18
|
config.logger.warn("#{e}\nURL:#{url}\nparams:#{params}")
|
19
|
-
|
20
|
-
false
|
19
|
+
raise 'Split SDK failed to connect to backend to retrieve information'
|
21
20
|
end
|
22
21
|
|
23
22
|
def post_api(url, config, api_key, data, headers = {}, params = {})
|
@@ -1,6 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Api
|
5
|
+
# Retrieves segment changes from the Split Backend
|
3
6
|
class Segments < Client
|
7
|
+
METRICS_PREFIX = 'segmentChangeFetcher'
|
8
|
+
|
4
9
|
def initialize(api_key, config, metrics, segments_repository)
|
5
10
|
@config = config
|
6
11
|
@metrics = metrics
|
@@ -10,52 +15,53 @@ module SplitIoClient
|
|
10
15
|
|
11
16
|
def store_segments_by_names(names)
|
12
17
|
start = Time.now
|
13
|
-
prefix = 'segmentChangeFetcher'
|
14
18
|
|
15
19
|
return if names.nil? || names.empty?
|
16
20
|
|
17
21
|
names.each do |name|
|
18
22
|
since = @segments_repository.get_change_number(name)
|
19
|
-
|
20
|
-
|
21
|
-
@
|
23
|
+
loop do
|
24
|
+
segment = fetch_segment_changes(name, since)
|
25
|
+
@segments_repository.add_to_segment(segment)
|
22
26
|
|
23
|
-
|
27
|
+
SplitLogger.log_if_debug("Segment #{name} fetched before: #{since}, \
|
28
|
+
till: #{@segments_repository.get_change_number(name)}")
|
29
|
+
|
30
|
+
break if since.to_i >= @segments_repository.get_change_number(name).to_i
|
24
31
|
since = @segments_repository.get_change_number(name)
|
25
32
|
end
|
26
33
|
end
|
27
34
|
|
28
35
|
latency = (Time.now - start) * 1000.0
|
29
|
-
@metrics.time(
|
36
|
+
@metrics.time(METRICS_PREFIX + '.time', latency)
|
30
37
|
end
|
31
38
|
|
32
39
|
private
|
33
40
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
@config.logger.debug("\'#{segment_content[:name]}\' #{segment_content[:removed].size} removed keys") if segment_content[:removed].size > 0
|
41
|
+
def fetch_segment_changes(name, since)
|
42
|
+
response = get_api("#{@config.base_uri}/segmentChanges/#{name}", @config, @api_key, since: since)
|
43
|
+
|
44
|
+
if response.success?
|
45
|
+
segment = JSON.parse(response.body, symbolize_names: true)
|
46
|
+
@segments_repository.set_change_number(name, segment[:till])
|
47
|
+
@metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
|
48
|
+
|
49
|
+
SplitLogger.log_if_debug("\'#{segment[:name]}\' segment retrieved.")
|
50
|
+
unless segment[:added].empty?
|
51
|
+
SplitLogger.log_if_debug("\'#{segment[:name]}\' #{segment[:added].size} added keys")
|
52
|
+
end
|
53
|
+
unless segment[:removed].empty?
|
54
|
+
SplitLogger.log_if_debug("\'#{segment[:name]}\' #{segment[:removed].size} removed keys")
|
49
55
|
end
|
50
|
-
|
56
|
+
SplitLogger.log_if_transport(segment.to_s)
|
51
57
|
|
52
|
-
|
58
|
+
segment
|
53
59
|
else
|
54
|
-
|
55
|
-
|
60
|
+
SplitLogger.log_error("Unexpected status code while fetching segments: #{response.status}." \
|
61
|
+
"Since #{since} - Check your API key and base URI")
|
62
|
+
@metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
|
63
|
+
raise 'Split SDK failed to connect to backend to fetch segments'
|
56
64
|
end
|
57
|
-
|
58
|
-
segments
|
59
65
|
end
|
60
66
|
end
|
61
67
|
end
|
@@ -1,6 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Api
|
5
|
+
# Retrieves split definitions from the Split Backend
|
3
6
|
class Splits < Client
|
7
|
+
METRICS_PREFIX = 'splitChangeFetcher'
|
8
|
+
|
4
9
|
def initialize(api_key, config, metrics)
|
5
10
|
@api_key = api_key
|
6
11
|
@config = config
|
@@ -9,28 +14,28 @@ module SplitIoClient
|
|
9
14
|
|
10
15
|
def since(since)
|
11
16
|
start = Time.now
|
12
|
-
prefix = 'splitChangeFetcher'
|
13
|
-
splits = get_api("#{@config.base_uri}/splitChanges", @config, @api_key, since: since)
|
14
17
|
|
15
|
-
|
16
|
-
@config.logger.error("Failed to make a http request")
|
17
|
-
elsif splits.status / 100 == 2
|
18
|
-
result = splits_with_segment_names(splits.body)
|
18
|
+
response = get_api("#{@config.base_uri}/splitChanges", @config, @api_key, since: since)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
@config.logger.debug("#{result[:splits].length} splits retrieved. since=#{since}") if @config.debug_enabled and result[:splits].length > 0
|
23
|
-
@config.logger.debug("#{result}") if @config.transport_debug_enabled
|
24
|
-
else
|
25
|
-
@metrics.count(prefix + '.status.' + splits.status.to_s, 1)
|
20
|
+
if response.success?
|
21
|
+
result = splits_with_segment_names(response.body)
|
26
22
|
|
27
|
-
@
|
28
|
-
|
23
|
+
@metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
|
24
|
+
unless result[:splits].empty?
|
25
|
+
SplitLogger.log_if_debug("#{result[:splits].length} splits retrieved. since=#{since}")
|
26
|
+
end
|
27
|
+
SplitLogger.log_if_transport(result.to_s)
|
29
28
|
|
30
|
-
|
31
|
-
|
29
|
+
latency = (Time.now - start) * 1000.0
|
30
|
+
@metrics.time(METRICS_PREFIX + '.time', latency)
|
32
31
|
|
33
|
-
|
32
|
+
result
|
33
|
+
else
|
34
|
+
@metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
|
35
|
+
SplitLogger.log_error("Unexpected status code while fetching splits: #{response.status}. " \
|
36
|
+
'Check your API key and base URI')
|
37
|
+
raise 'Split SDK failed to connect to backend to fetch split definitions'
|
38
|
+
end
|
34
39
|
end
|
35
40
|
|
36
41
|
private
|
@@ -76,7 +76,7 @@ module SplitIoClient
|
|
76
76
|
@events_adapter = SplitConfig.init_cache_adapter(
|
77
77
|
opts[:cache_adapter] || SplitConfig.default_cache_adapter, :queue_adapter, @redis_url, @events_queue_size
|
78
78
|
)
|
79
|
-
|
79
|
+
SplitIoClient::SplitLogger.split_config(self)
|
80
80
|
startup_log
|
81
81
|
end
|
82
82
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
class SplitLogger
|
5
|
+
attr_accessor :config
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def self.split_config(config)
|
9
|
+
instance.config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def log_if_debug(message)
|
13
|
+
config.logger.debug(message) if config.debug_enabled
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_if_transport(message)
|
17
|
+
config.logger.debug(message) if config.transport_debug_enabled
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_error(message)
|
21
|
+
config.logger.error(message)
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
extend Forwardable
|
26
|
+
def_delegators :instance, *SplitLogger.instance_methods(false)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/splitclient-rb.gemspec
CHANGED
@@ -1,53 +1,57 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'splitclient-rb/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'splitclient-rb'
|
8
9
|
spec.version = SplitIoClient::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['Split Software']
|
11
|
+
spec.email = ['pato@split.io']
|
11
12
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
13
|
+
spec.summary = 'Ruby client for split SDK.'
|
14
|
+
spec.description = 'Ruby client for using split SDK.'
|
15
|
+
spec.homepage = 'https://github.com/splitio/ruby-client'
|
16
|
+
spec.license = 'Apache 2.0'
|
16
17
|
|
17
18
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|features|ext)/}) }
|
18
19
|
|
19
|
-
spec.bindir =
|
20
|
+
spec.bindir = 'exe'
|
20
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ['lib']
|
22
23
|
|
23
24
|
if defined?(JRUBY_VERSION)
|
24
25
|
spec.platform = 'java'
|
25
|
-
spec.files.concat(
|
26
|
-
ext/murmurhash/MurmurHash3.java
|
27
|
-
|
26
|
+
spec.files.concat(
|
27
|
+
%w[ext/murmurhash/MurmurHash3.java
|
28
|
+
lib/murmurhash/murmurhash.jar]
|
28
29
|
)
|
29
30
|
else
|
30
|
-
spec.files.concat(
|
31
|
-
ext/murmurhash/3_x86_32.c
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
spec.files.concat(
|
32
|
+
%w[ext/murmurhash/3_x86_32.c
|
33
|
+
ext/murmurhash/extconf.rb
|
34
|
+
ext/murmurhash/murmurhash.c
|
35
|
+
ext/murmurhash/murmurhash.h]
|
35
36
|
)
|
36
|
-
spec.extensions = [
|
37
|
+
spec.extensions = ['ext/murmurhash/extconf.rb']
|
37
38
|
end
|
38
39
|
|
39
|
-
spec.add_development_dependency
|
40
|
-
spec.add_development_dependency
|
41
|
-
spec.add_development_dependency
|
42
|
-
spec.add_development_dependency
|
43
|
-
spec.add_development_dependency
|
44
|
-
spec.add_development_dependency
|
45
|
-
spec.add_development_dependency
|
46
|
-
|
47
|
-
spec.
|
48
|
-
spec.
|
49
|
-
|
50
|
-
spec.add_runtime_dependency
|
51
|
-
spec.add_runtime_dependency
|
52
|
-
spec.add_runtime_dependency
|
40
|
+
spec.add_development_dependency 'allocation_stats'
|
41
|
+
spec.add_development_dependency 'bundler', '~> 1.11'
|
42
|
+
spec.add_development_dependency 'pry'
|
43
|
+
spec.add_development_dependency 'pry-nav'
|
44
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
45
|
+
spec.add_development_dependency 'rake-compiler'
|
46
|
+
spec.add_development_dependency 'rspec'
|
47
|
+
spec.add_development_dependency 'rubocop'
|
48
|
+
spec.add_development_dependency 'simplecov'
|
49
|
+
spec.add_development_dependency 'webmock'
|
50
|
+
|
51
|
+
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
52
|
+
spec.add_runtime_dependency 'faraday', '>= 0.8'
|
53
|
+
spec.add_runtime_dependency 'json', '>= 1.8'
|
54
|
+
spec.add_runtime_dependency 'net-http-persistent', '~> 2.9'
|
55
|
+
spec.add_runtime_dependency 'redis', '>= 3.2'
|
56
|
+
spec.add_runtime_dependency 'thread_safe', '>= 0.3'
|
53
57
|
end
|