splitclient-rb 7.3.1.pre.rc1-java → 7.3.2.pre.rc4-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/.github/workflows/ci.yml +78 -0
- data/CHANGES.txt +3 -0
- data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +3 -9
- data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +3 -6
- data/lib/splitclient-rb/cache/stores/localhost_split_store.rb +3 -6
- data/lib/splitclient-rb/clients/split_client.rb +5 -5
- data/lib/splitclient-rb/engine/common/impressions_manager.rb +4 -4
- data/lib/splitclient-rb/engine/status_manager.rb +33 -0
- data/lib/splitclient-rb/engine/sync_manager.rb +27 -48
- data/lib/splitclient-rb/engine/synchronizer.rb +19 -14
- data/lib/splitclient-rb/managers/split_manager.rb +4 -4
- data/lib/splitclient-rb/split_factory.rb +27 -23
- data/lib/splitclient-rb/sse/event_source/client.rb +3 -2
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +2 -2
- data/splitclient-rb.gemspec +3 -2
- metadata +21 -8
- data/.travis.yml +0 -20
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +0 -64
- data/sonar-scanner.sh +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b34d8922cda5b9c044086cb712fad521bfa4d07a
|
4
|
+
data.tar.gz: 41303bbf93181d1b234f49ffafa4e23493afde97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df2d6c00758d77c566070db80c73628b0aaaacad749c626cc695c9787d7c5be45ce17c708e8a4a41353493392463fad8c5a8c161266c5e48f3f847b919b0e62e
|
7
|
+
data.tar.gz: 434b227c0d090209143923166ad7be6ae40ab760f5ba26b5e2ac32e4c9b056d3c9b7cd73830a5872ccd7eb0c9b46402d1d6cbeaab0154fbdf528ed5cd8119415
|
@@ -0,0 +1,78 @@
|
|
1
|
+
on:
|
2
|
+
push:
|
3
|
+
branches:
|
4
|
+
- master
|
5
|
+
pull_request:
|
6
|
+
branches:
|
7
|
+
- master
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
services:
|
13
|
+
redis:
|
14
|
+
image: redis
|
15
|
+
ports:
|
16
|
+
- 6379:6379
|
17
|
+
steps:
|
18
|
+
- name: Checkout code
|
19
|
+
uses: actions/checkout@v2
|
20
|
+
with:
|
21
|
+
fetch-depth: 0
|
22
|
+
|
23
|
+
- name: Set up Ruby
|
24
|
+
uses: ruby/setup-ruby@477b21f02be01bcb8030d50f37cfec92bfa615b6
|
25
|
+
with:
|
26
|
+
ruby-version: 2.5
|
27
|
+
|
28
|
+
- name: Install dependencies
|
29
|
+
run: bundle install
|
30
|
+
|
31
|
+
- name: Run tests
|
32
|
+
run: bundle exec rake
|
33
|
+
|
34
|
+
- name: Fix code coverage paths
|
35
|
+
working-directory: ./coverage
|
36
|
+
run: |
|
37
|
+
sed -i 's@'$GITHUB_WORKSPACE'@/github/workspace/@g' .resultset.json
|
38
|
+
ruby -rjson -e 'sqube = JSON.load(File.read(".resultset.json"))["RSpec"]["coverage"].transform_values {|lines| lines["lines"]}; total = { "RSpec" => { "coverage" => sqube, "timestamp" => Time.now.to_i }}; puts JSON.dump(total)' > .resultset.sonarqube.json
|
39
|
+
|
40
|
+
|
41
|
+
- name: SonarQube Scan (Push)
|
42
|
+
if: github.event_name == 'push'
|
43
|
+
uses: SonarSource/sonarcloud-github-action@v1.5
|
44
|
+
env:
|
45
|
+
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
46
|
+
with:
|
47
|
+
projectBaseDir: .
|
48
|
+
args: >
|
49
|
+
-Dsonar.host.url=${{ secrets.SONARQUBE_HOST }}
|
50
|
+
-Dsonar.projectName=${{ github.event.repository.name }}
|
51
|
+
-Dsonar.projectKey=${{ github.event.repository.name }}
|
52
|
+
-Dsonar.ruby.coverage.reportPaths=coverage/.resultset.sonarqube.json
|
53
|
+
-Dsonar.c.file.suffixes=-
|
54
|
+
-Dsonar.cpp.file.suffixes=-
|
55
|
+
-Dsonar.objc.file.suffixes=-
|
56
|
+
-Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions"
|
57
|
+
-Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}"
|
58
|
+
|
59
|
+
- name: SonarQube Scan (Pull Request)
|
60
|
+
if: github.event_name == 'pull_request'
|
61
|
+
uses: SonarSource/sonarcloud-github-action@v1.5
|
62
|
+
env:
|
63
|
+
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
64
|
+
with:
|
65
|
+
projectBaseDir: .
|
66
|
+
args: >
|
67
|
+
-Dsonar.host.url=${{ secrets.SONARQUBE_HOST }}
|
68
|
+
-Dsonar.projectName=${{ github.event.repository.name }}
|
69
|
+
-Dsonar.projectKey=${{ github.event.repository.name }}
|
70
|
+
-Dsonar.ruby.coverage.reportPaths=coverage/.resultset.sonarqube.json
|
71
|
+
-Dsonar.c.file.suffixes=-
|
72
|
+
-Dsonar.cpp.file.suffixes=-
|
73
|
+
-Dsonar.objc.file.suffixes=-
|
74
|
+
-Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions"
|
75
|
+
-Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}"
|
76
|
+
-Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
|
77
|
+
-Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }}
|
78
|
+
-Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }}
|
data/CHANGES.txt
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
CHANGES
|
2
2
|
|
3
|
+
7.3.1 (Jul 26, 2021)
|
4
|
+
- Updated the synchronization flow to be more reliable in the event of an edge case generating delay in cache purge propagation, keeping the SDK cache properly synced.
|
5
|
+
|
3
6
|
7.3.0 (Jul 12, 2021)
|
4
7
|
- Updated SDK telemetry storage, metrics and updater to be more effective and send less often.
|
5
8
|
- Fixed high cpu usage when api key is wrong.
|
@@ -4,11 +4,10 @@ module SplitIoClient
|
|
4
4
|
class SegmentFetcher
|
5
5
|
attr_reader :segments_repository
|
6
6
|
|
7
|
-
def initialize(segments_repository, api_key, config,
|
7
|
+
def initialize(segments_repository, api_key, config, telemetry_runtime_producer)
|
8
8
|
@segments_repository = segments_repository
|
9
9
|
@api_key = api_key
|
10
10
|
@config = config
|
11
|
-
@sdk_blocker = sdk_blocker
|
12
11
|
@semaphore = Mutex.new
|
13
12
|
@telemetry_runtime_producer = telemetry_runtime_producer
|
14
13
|
end
|
@@ -52,11 +51,11 @@ module SplitIoClient
|
|
52
51
|
@semaphore.synchronize do
|
53
52
|
segments_api.fetch_segments_by_names(@segments_repository.used_segment_names)
|
54
53
|
|
55
|
-
|
56
|
-
@sdk_blocker.sdk_internal_ready
|
54
|
+
true
|
57
55
|
end
|
58
56
|
rescue StandardError => error
|
59
57
|
@config.log_found_exception(__method__.to_s, error)
|
58
|
+
false
|
60
59
|
end
|
61
60
|
|
62
61
|
def stop_segments_thread
|
@@ -70,11 +69,6 @@ module SplitIoClient
|
|
70
69
|
@config.logger.info('Starting segments fetcher service') if @config.debug_enabled
|
71
70
|
|
72
71
|
loop do
|
73
|
-
unless @sdk_blocker.splits_repository.ready?
|
74
|
-
sleep 0.2
|
75
|
-
next
|
76
|
-
end
|
77
|
-
|
78
72
|
fetch_segments
|
79
73
|
@config.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if @config.debug_enabled
|
80
74
|
|
@@ -4,11 +4,10 @@ module SplitIoClient
|
|
4
4
|
class SplitFetcher
|
5
5
|
attr_reader :splits_repository
|
6
6
|
|
7
|
-
def initialize(splits_repository, api_key, config,
|
7
|
+
def initialize(splits_repository, api_key, config, telemetry_runtime_producer)
|
8
8
|
@splits_repository = splits_repository
|
9
9
|
@api_key = api_key
|
10
10
|
@config = config
|
11
|
-
@sdk_blocker = sdk_blocker
|
12
11
|
@semaphore = Mutex.new
|
13
12
|
@telemetry_runtime_producer = telemetry_runtime_producer
|
14
13
|
end
|
@@ -40,13 +39,11 @@ module SplitIoClient
|
|
40
39
|
|
41
40
|
@config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
data[:segment_names]
|
42
|
+
{ segment_names: data[:segment_names], success: true }
|
46
43
|
end
|
47
44
|
rescue StandardError => error
|
48
45
|
@config.log_found_exception(__method__.to_s, error)
|
49
|
-
[]
|
46
|
+
{ segment_names: [], success: false }
|
50
47
|
end
|
51
48
|
|
52
49
|
def stop_splits_thread
|
@@ -7,10 +7,10 @@ module SplitIoClient
|
|
7
7
|
require 'yaml'
|
8
8
|
attr_reader :splits_repository
|
9
9
|
|
10
|
-
def initialize(splits_repository, config,
|
10
|
+
def initialize(splits_repository, config, status_manager = nil)
|
11
11
|
@splits_repository = splits_repository
|
12
12
|
@config = config
|
13
|
-
@
|
13
|
+
@status_manager = status_manager
|
14
14
|
end
|
15
15
|
|
16
16
|
def call
|
@@ -45,10 +45,7 @@ module SplitIoClient
|
|
45
45
|
store_split(split)
|
46
46
|
end
|
47
47
|
|
48
|
-
if @
|
49
|
-
@sdk_blocker.splits_ready!
|
50
|
-
@sdk_blocker.segments_ready!
|
51
|
-
end
|
48
|
+
@status_manager.ready! if @status_manager
|
52
49
|
rescue StandardError => error
|
53
50
|
@config.logger.error('Error while parsing the split file. ' \
|
54
51
|
'Check that the input file matches the expected format')
|
@@ -14,13 +14,13 @@ module SplitIoClient
|
|
14
14
|
# @param api_key [String] the API key for your split account
|
15
15
|
#
|
16
16
|
# @return [SplitIoClient] split.io client instance
|
17
|
-
def initialize(api_key, repositories,
|
17
|
+
def initialize(api_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer)
|
18
18
|
@api_key = api_key
|
19
19
|
@splits_repository = repositories[:splits]
|
20
20
|
@segments_repository = repositories[:segments]
|
21
21
|
@impressions_repository = repositories[:impressions]
|
22
22
|
@events_repository = repositories[:events]
|
23
|
-
@
|
23
|
+
@status_manager = status_manager
|
24
24
|
@destroyed = false
|
25
25
|
@config = config
|
26
26
|
@impressions_manager = impressions_manager
|
@@ -137,7 +137,7 @@ module SplitIoClient
|
|
137
137
|
else
|
138
138
|
{
|
139
139
|
treatment: treatment_data[:treatment],
|
140
|
-
config: treatment_data[:config]
|
140
|
+
config: treatment_data[:config],
|
141
141
|
}
|
142
142
|
end
|
143
143
|
end
|
@@ -157,7 +157,7 @@ module SplitIoClient
|
|
157
157
|
end
|
158
158
|
|
159
159
|
def block_until_ready(time = nil)
|
160
|
-
@
|
160
|
+
@status_manager.wait_until_ready(time) if @status_manager
|
161
161
|
end
|
162
162
|
|
163
163
|
private
|
@@ -310,7 +310,7 @@ module SplitIoClient
|
|
310
310
|
end
|
311
311
|
|
312
312
|
def ready?
|
313
|
-
return @
|
313
|
+
return @status_manager.ready? if @status_manager
|
314
314
|
true
|
315
315
|
end
|
316
316
|
|
@@ -21,8 +21,8 @@ module SplitIoClient
|
|
21
21
|
@impression_counter.inc(split_name, impression_data[:m]) if optimized? && !redis?
|
22
22
|
|
23
23
|
impression(impression_data, params[:attributes])
|
24
|
-
rescue StandardError =>
|
25
|
-
@config.log_found_exception(__method__.to_s,
|
24
|
+
rescue StandardError => e
|
25
|
+
@config.log_found_exception(__method__.to_s, e)
|
26
26
|
end
|
27
27
|
|
28
28
|
def track(impressions)
|
@@ -48,8 +48,8 @@ module SplitIoClient
|
|
48
48
|
end
|
49
49
|
|
50
50
|
record_stats(queued, dropped, dedupe)
|
51
|
-
rescue StandardError =>
|
52
|
-
@config.log_found_exception(__method__.to_s,
|
51
|
+
rescue StandardError => e
|
52
|
+
@config.log_found_exception(__method__.to_s, e)
|
53
53
|
end
|
54
54
|
|
55
55
|
private
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module Engine
|
5
|
+
class StatusManager
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
@sdk_ready = Concurrent::CountDownLatch.new(1)
|
9
|
+
end
|
10
|
+
|
11
|
+
def ready?
|
12
|
+
return true if @config.consumer?
|
13
|
+
|
14
|
+
@sdk_ready.wait(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
def ready!
|
18
|
+
return if ready?
|
19
|
+
|
20
|
+
@sdk_ready.count_down
|
21
|
+
@config.logger.info('SplitIO SDK is ready')
|
22
|
+
end
|
23
|
+
|
24
|
+
def wait_until_ready(seconds = nil)
|
25
|
+
return if @config.consumer?
|
26
|
+
|
27
|
+
timeout = seconds || @config.block_until_ready
|
28
|
+
|
29
|
+
raise SDKBlockerTimeoutExpiredException, 'SDK start up timeout expired' unless @sdk_ready.wait(timeout)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -12,8 +12,8 @@ module SplitIoClient
|
|
12
12
|
config,
|
13
13
|
synchronizer,
|
14
14
|
telemetry_runtime_producer,
|
15
|
-
|
16
|
-
|
15
|
+
telemetry_synchronizer,
|
16
|
+
status_manager
|
17
17
|
)
|
18
18
|
@synchronizer = synchronizer
|
19
19
|
notification_manager_keeper = SSE::NotificationManagerKeeper.new(config, telemetry_runtime_producer) do |manager|
|
@@ -33,55 +33,41 @@ module SplitIoClient
|
|
33
33
|
@sse_connected = Concurrent::AtomicBoolean.new(false)
|
34
34
|
@config = config
|
35
35
|
@telemetry_runtime_producer = telemetry_runtime_producer
|
36
|
-
@sdk_blocker = sdk_blocker
|
37
36
|
@telemetry_synchronizer = telemetry_synchronizer
|
37
|
+
@status_manager = status_manager
|
38
38
|
end
|
39
39
|
|
40
40
|
def start
|
41
|
-
|
42
|
-
|
43
|
-
start_stream_forked if defined?(PhusionPassenger)
|
44
|
-
elsif @config.standalone?
|
45
|
-
start_poll
|
46
|
-
end
|
47
|
-
|
48
|
-
synchronize_telemetry_config
|
41
|
+
start_thread
|
42
|
+
PhusionPassenger.on_event(:starting_worker_process) { |forked| start_thread if forked } if defined?(PhusionPassenger)
|
49
43
|
end
|
50
44
|
|
51
45
|
private
|
52
46
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
@synchronizer.sync_all
|
57
|
-
@synchronizer.start_periodic_data_recording
|
58
|
-
|
59
|
-
start_sse_connection_thread
|
60
|
-
end
|
47
|
+
def start_thread
|
48
|
+
@config.threads[:start_sdk] = Thread.new do
|
49
|
+
sleep(0.5) until @synchronizer.sync_all(false)
|
61
50
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
record_telemetry(Telemetry::Domain::Constants::SYNC_MODE, SYNC_MODE_POLLING)
|
67
|
-
rescue StandardError => e
|
68
|
-
@config.logger.error("start_poll error : #{e.inspect}")
|
69
|
-
end
|
51
|
+
@status_manager.ready!
|
52
|
+
@telemetry_synchronizer.synchronize_config
|
53
|
+
@synchronizer.start_periodic_data_recording
|
54
|
+
connected = false
|
70
55
|
|
71
|
-
|
72
|
-
|
73
|
-
@config.threads[:sync_manager_start_sse] = Thread.new do
|
74
|
-
begin
|
56
|
+
if @config.streaming_enabled
|
57
|
+
@config.logger.debug('Starting Straming mode ...')
|
75
58
|
connected = @push_manager.start_sse
|
76
|
-
|
77
|
-
|
78
|
-
|
59
|
+
|
60
|
+
if defined?(PhusionPassenger)
|
61
|
+
PhusionPassenger.on_event(:starting_worker_process) { |forked| sse_thread_forked if forked }
|
62
|
+
end
|
79
63
|
end
|
80
|
-
end
|
81
|
-
end
|
82
64
|
|
83
|
-
|
84
|
-
|
65
|
+
unless connected
|
66
|
+
@config.logger.debug('Starting polling mode ...')
|
67
|
+
@synchronizer.start_periodic_fetch
|
68
|
+
record_telemetry(Telemetry::Domain::Constants::SYNC_MODE, SYNC_MODE_POLLING)
|
69
|
+
end
|
70
|
+
end
|
85
71
|
end
|
86
72
|
|
87
73
|
def process_action(action)
|
@@ -165,16 +151,9 @@ module SplitIoClient
|
|
165
151
|
@telemetry_runtime_producer.record_streaming_event(type, data)
|
166
152
|
end
|
167
153
|
|
168
|
-
def
|
169
|
-
|
170
|
-
|
171
|
-
@sdk_blocker.wait_unitil_internal_ready unless @config.consumer?
|
172
|
-
@telemetry_synchronizer.synchronize_config
|
173
|
-
rescue SplitIoClient::SDKShutdownException
|
174
|
-
@telemetry_synchronizer.synchronize_config
|
175
|
-
@config.logger.info('Posting Telemetry config due to shutdown')
|
176
|
-
end
|
177
|
-
end
|
154
|
+
def sse_thread_forked
|
155
|
+
connected = @push_manager.start_sse
|
156
|
+
@synchronizer.start_periodic_fetch unless connected
|
178
157
|
end
|
179
158
|
end
|
180
159
|
end
|
@@ -14,7 +14,6 @@ module SplitIoClient
|
|
14
14
|
repositories,
|
15
15
|
api_key,
|
16
16
|
config,
|
17
|
-
sdk_blocker,
|
18
17
|
params
|
19
18
|
)
|
20
19
|
@splits_repository = repositories[:splits]
|
@@ -23,7 +22,6 @@ module SplitIoClient
|
|
23
22
|
@events_repository = repositories[:events]
|
24
23
|
@api_key = api_key
|
25
24
|
@config = config
|
26
|
-
@sdk_blocker = sdk_blocker
|
27
25
|
@split_fetcher = params[:split_fetcher]
|
28
26
|
@segment_fetcher = params[:segment_fetcher]
|
29
27
|
@impressions_api = SplitIoClient::Api::Impressions.new(@api_key, @config, params[:telemetry_runtime_producer])
|
@@ -31,12 +29,16 @@ module SplitIoClient
|
|
31
29
|
@telemetry_synchronizer = params[:telemetry_synchronizer]
|
32
30
|
end
|
33
31
|
|
34
|
-
def sync_all
|
32
|
+
def sync_all(asynchronous = true)
|
33
|
+
unless asynchronous
|
34
|
+
return sync_splits_and_segments
|
35
|
+
end
|
36
|
+
|
35
37
|
@config.threads[:sync_all_thread] = Thread.new do
|
36
|
-
|
37
|
-
@split_fetcher.fetch_splits
|
38
|
-
@segment_fetcher.fetch_segments
|
38
|
+
sync_splits_and_segments
|
39
39
|
end
|
40
|
+
|
41
|
+
true
|
40
42
|
end
|
41
43
|
|
42
44
|
def start_periodic_data_recording
|
@@ -82,7 +84,7 @@ module SplitIoClient
|
|
82
84
|
nil,
|
83
85
|
true)
|
84
86
|
|
85
|
-
attempts =
|
87
|
+
attempts = ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES - result[:remaining_attempts]
|
86
88
|
|
87
89
|
if result[:success]
|
88
90
|
@segment_fetcher.fetch_segments_if_not_exists(result[:segment_names], true) unless result[:segment_names].empty?
|
@@ -156,20 +158,16 @@ module SplitIoClient
|
|
156
158
|
loop do
|
157
159
|
remaining_attempts -= 1
|
158
160
|
|
159
|
-
|
161
|
+
result = @split_fetcher.fetch_splits(fetch_options)
|
160
162
|
|
161
|
-
return sync_result(true, remaining_attempts, segment_names) if target_cn <= @splits_repository.get_change_number
|
162
|
-
return sync_result(false, remaining_attempts, segment_names) if remaining_attempts <= 0
|
163
|
+
return sync_result(true, remaining_attempts, result[:segment_names]) if target_cn <= @splits_repository.get_change_number
|
164
|
+
return sync_result(false, remaining_attempts, result[:segment_names]) if remaining_attempts <= 0
|
163
165
|
|
164
166
|
delay = with_backoff ? backoff.interval : retry_delay_seconds
|
165
167
|
sleep(delay)
|
166
168
|
end
|
167
169
|
end
|
168
170
|
|
169
|
-
def fetch_segments
|
170
|
-
@segment_fetcher.fetch_segments
|
171
|
-
end
|
172
|
-
|
173
171
|
# Starts thread which loops constantly and sends impressions to the Split API
|
174
172
|
def impressions_sender
|
175
173
|
ImpressionsSender.new(@impressions_repository, @config, @impressions_api).call
|
@@ -192,6 +190,13 @@ module SplitIoClient
|
|
192
190
|
def sync_result(success, remaining_attempts, segment_names = nil)
|
193
191
|
{ success: success, remaining_attempts: remaining_attempts, segment_names: segment_names }
|
194
192
|
end
|
193
|
+
|
194
|
+
def sync_splits_and_segments
|
195
|
+
@config.logger.debug('Synchronizing Splits and Segments ...') if @config.debug_enabled
|
196
|
+
splits_result = @split_fetcher.fetch_splits
|
197
|
+
|
198
|
+
splits_result[:success] && @segment_fetcher.fetch_segments
|
199
|
+
end
|
195
200
|
end
|
196
201
|
end
|
197
202
|
end
|
@@ -4,9 +4,9 @@ module SplitIoClient
|
|
4
4
|
# Creates a new split manager instance that connects to split.io API.
|
5
5
|
#
|
6
6
|
# @return [SplitIoManager] split.io client instance
|
7
|
-
def initialize(splits_repository = nil,
|
7
|
+
def initialize(splits_repository = nil, status_manager, config)
|
8
8
|
@splits_repository = splits_repository
|
9
|
-
@
|
9
|
+
@status_manager = status_manager
|
10
10
|
@config = config
|
11
11
|
end
|
12
12
|
|
@@ -78,7 +78,7 @@ module SplitIoClient
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def block_until_ready(time = nil)
|
81
|
-
@
|
81
|
+
@status_manager.wait_until_ready(time) if @status_manager
|
82
82
|
end
|
83
83
|
|
84
84
|
private
|
@@ -111,7 +111,7 @@ module SplitIoClient
|
|
111
111
|
|
112
112
|
# move to blocker, alongside block until ready to avoid duplication
|
113
113
|
def ready?
|
114
|
-
return @
|
114
|
+
return @status_manager.ready? if @status_manager
|
115
115
|
true
|
116
116
|
end
|
117
117
|
end
|
@@ -28,45 +28,49 @@ module SplitIoClient
|
|
28
28
|
|
29
29
|
raise 'Invalid SDK mode' unless valid_mode
|
30
30
|
|
31
|
+
validate_api_key
|
32
|
+
|
33
|
+
register_factory
|
34
|
+
|
31
35
|
build_telemetry_components
|
32
36
|
|
33
37
|
@splits_repository = SplitsRepository.new(@config)
|
34
38
|
@segments_repository = SegmentsRepository.new(@config)
|
35
39
|
@impressions_repository = ImpressionsRepository.new(@config)
|
36
40
|
@events_repository = EventsRepository.new(@config, @api_key, @runtime_producer)
|
37
|
-
@sdk_blocker = SDKBlocker.new(@splits_repository, @segments_repository, @config)
|
38
41
|
@impression_counter = SplitIoClient::Engine::Common::ImpressionCounter.new
|
39
42
|
@impressions_manager = SplitIoClient::Engine::Common::ImpressionManager.new(@config, @impressions_repository, @impression_counter, @runtime_producer)
|
40
43
|
@telemetry_api = SplitIoClient::Api::TelemetryApi.new(@config, @api_key, @runtime_producer)
|
41
44
|
@telemetry_synchronizer = Telemetry::Synchronizer.new(@config, @telemetry_consumers, @init_producer, repositories, @telemetry_api)
|
45
|
+
@status_manager = Engine::StatusManager.new(@config)
|
42
46
|
|
43
47
|
start!
|
44
48
|
|
45
|
-
@client = SplitClient.new(@api_key, repositories, @
|
46
|
-
@manager = SplitManager.new(@splits_repository, @
|
47
|
-
|
48
|
-
validate_api_key
|
49
|
-
|
50
|
-
register_factory
|
49
|
+
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer)
|
50
|
+
@manager = SplitManager.new(@splits_repository, @status_manager, @config)
|
51
51
|
end
|
52
52
|
|
53
53
|
def start!
|
54
|
-
if @config.localhost_mode
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
split_fetcher: split_fetcher,
|
61
|
-
segment_fetcher: segment_fetcher,
|
62
|
-
imp_counter: @impression_counter,
|
63
|
-
telemetry_runtime_producer: @runtime_producer,
|
64
|
-
telemetry_synchronizer: @telemetry_synchronizer
|
65
|
-
}
|
66
|
-
|
67
|
-
synchronizer = SplitIoClient::Engine::Synchronizer.new(repositories, @api_key, @config, @sdk_blocker, params)
|
68
|
-
SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, synchronizer, @runtime_producer, @sdk_blocker, @telemetry_synchronizer).start
|
54
|
+
return start_localhost_components if @config.localhost_mode
|
55
|
+
|
56
|
+
if @config.consumer?
|
57
|
+
@status_manager.ready!
|
58
|
+
@telemetry_synchronizer.synchronize_config
|
59
|
+
return
|
69
60
|
end
|
61
|
+
|
62
|
+
split_fetcher = SplitFetcher.new(@splits_repository, @api_key, config, @runtime_producer)
|
63
|
+
segment_fetcher = SegmentFetcher.new(@segments_repository, @api_key, config, @runtime_producer)
|
64
|
+
params = {
|
65
|
+
split_fetcher: split_fetcher,
|
66
|
+
segment_fetcher: segment_fetcher,
|
67
|
+
imp_counter: @impression_counter,
|
68
|
+
telemetry_runtime_producer: @runtime_producer,
|
69
|
+
telemetry_synchronizer: @telemetry_synchronizer
|
70
|
+
}
|
71
|
+
|
72
|
+
synchronizer = SplitIoClient::Engine::Synchronizer.new(repositories, @api_key, @config, params)
|
73
|
+
SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, synchronizer, @runtime_producer, @telemetry_synchronizer, @status_manager).start
|
70
74
|
end
|
71
75
|
|
72
76
|
def stop!
|
@@ -145,7 +149,7 @@ module SplitIoClient
|
|
145
149
|
end
|
146
150
|
|
147
151
|
def start_localhost_components
|
148
|
-
LocalhostSplitStore.new(@splits_repository, @config, @
|
152
|
+
LocalhostSplitStore.new(@splits_repository, @config, @status_manager).call
|
149
153
|
|
150
154
|
# Starts thread which loops constantly and cleans up repositories to avoid memory issues in localhost mode
|
151
155
|
LocalhostRepoCleaner.new(@impressions_repository, @events_repository, @config).call
|
@@ -77,7 +77,7 @@ module SplitIoClient
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def connect_stream(latch)
|
80
|
-
socket_write
|
80
|
+
socket_write(latch)
|
81
81
|
|
82
82
|
while connected? || @first_event.value
|
83
83
|
begin
|
@@ -96,13 +96,14 @@ module SplitIoClient
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
def socket_write
|
99
|
+
def socket_write(latch)
|
100
100
|
@first_event.make_true
|
101
101
|
@socket = socket_connect
|
102
102
|
@socket.write(build_request(@uri))
|
103
103
|
rescue StandardError => e
|
104
104
|
@config.logger.error("Error during connecting to #{@uri.host}. Error: #{e.inspect}")
|
105
105
|
close(Constants::PUSH_NONRETRYABLE_ERROR)
|
106
|
+
latch.count_down
|
106
107
|
end
|
107
108
|
|
108
109
|
def read_first_event(data, latch)
|
data/lib/splitclient-rb.rb
CHANGED
@@ -28,10 +28,9 @@ require 'splitclient-rb/cache/senders/impressions_sender'
|
|
28
28
|
require 'splitclient-rb/cache/senders/events_sender'
|
29
29
|
require 'splitclient-rb/cache/senders/impressions_count_sender'
|
30
30
|
require 'splitclient-rb/cache/senders/localhost_repo_cleaner'
|
31
|
-
require 'splitclient-rb/cache/stores/store_utils'
|
32
31
|
require 'splitclient-rb/cache/stores/localhost_split_builder'
|
33
|
-
require 'splitclient-rb/cache/stores/sdk_blocker'
|
34
32
|
require 'splitclient-rb/cache/stores/localhost_split_store'
|
33
|
+
require 'splitclient-rb/cache/stores/store_utils'
|
35
34
|
|
36
35
|
require 'splitclient-rb/clients/split_client'
|
37
36
|
require 'splitclient-rb/managers/split_manager'
|
@@ -87,6 +86,7 @@ require 'splitclient-rb/engine/models/treatment'
|
|
87
86
|
require 'splitclient-rb/engine/auth_api_client'
|
88
87
|
require 'splitclient-rb/engine/back_off'
|
89
88
|
require 'splitclient-rb/engine/push_manager'
|
89
|
+
require 'splitclient-rb/engine/status_manager'
|
90
90
|
require 'splitclient-rb/engine/sync_manager'
|
91
91
|
require 'splitclient-rb/engine/synchronizer'
|
92
92
|
require 'splitclient-rb/utilitites'
|
data/splitclient-rb.gemspec
CHANGED
@@ -38,14 +38,15 @@ Gem::Specification.new do |spec|
|
|
38
38
|
|
39
39
|
spec.add_development_dependency 'allocation_stats'
|
40
40
|
spec.add_development_dependency 'appraisal'
|
41
|
-
spec.add_development_dependency 'bundler', '~>
|
41
|
+
spec.add_development_dependency 'bundler', '~> 2.2'
|
42
42
|
spec.add_development_dependency 'pry'
|
43
43
|
spec.add_development_dependency 'pry-nav'
|
44
44
|
spec.add_development_dependency 'rake', '12.3.3'
|
45
45
|
spec.add_development_dependency 'rake-compiler'
|
46
46
|
spec.add_development_dependency 'rspec'
|
47
47
|
spec.add_development_dependency 'rubocop', '0.59.0'
|
48
|
-
spec.add_development_dependency 'simplecov'
|
48
|
+
spec.add_development_dependency 'simplecov', '0.20.0'
|
49
|
+
spec.add_development_dependency 'simplecov-json'
|
49
50
|
spec.add_development_dependency 'timecop'
|
50
51
|
spec.add_development_dependency 'webmock'
|
51
52
|
|
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: 7.3.
|
4
|
+
version: 7.3.2.pre.rc4
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '2.2'
|
47
47
|
name: bundler
|
48
48
|
prerelease: false
|
49
49
|
type: :development
|
@@ -51,7 +51,7 @@ dependencies:
|
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
@@ -136,13 +136,27 @@ dependencies:
|
|
136
136
|
- - '='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 0.59.0
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - '='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 0.20.0
|
145
|
+
name: simplecov
|
146
|
+
prerelease: false
|
147
|
+
type: :development
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.20.0
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
requirement: !ruby/object:Gem::Requirement
|
141
155
|
requirements:
|
142
156
|
- - ">="
|
143
157
|
- !ruby/object:Gem::Version
|
144
158
|
version: '0'
|
145
|
-
name: simplecov
|
159
|
+
name: simplecov-json
|
146
160
|
prerelease: false
|
147
161
|
type: :development
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -312,10 +326,10 @@ extensions: []
|
|
312
326
|
extra_rdoc_files: []
|
313
327
|
files:
|
314
328
|
- ".github/pull_request_template.md"
|
329
|
+
- ".github/workflows/ci.yml"
|
315
330
|
- ".gitignore"
|
316
331
|
- ".rubocop.yml"
|
317
332
|
- ".simplecov"
|
318
|
-
- ".travis.yml"
|
319
333
|
- Appraisals
|
320
334
|
- CHANGES.txt
|
321
335
|
- CONTRIBUTORS-GUIDE.md
|
@@ -356,7 +370,6 @@ files:
|
|
356
370
|
- lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb
|
357
371
|
- lib/splitclient-rb/cache/stores/localhost_split_builder.rb
|
358
372
|
- lib/splitclient-rb/cache/stores/localhost_split_store.rb
|
359
|
-
- lib/splitclient-rb/cache/stores/sdk_blocker.rb
|
360
373
|
- lib/splitclient-rb/cache/stores/store_utils.rb
|
361
374
|
- lib/splitclient-rb/clients/split_client.rb
|
362
375
|
- lib/splitclient-rb/constants.rb
|
@@ -403,6 +416,7 @@ files:
|
|
403
416
|
- lib/splitclient-rb/engine/parser/evaluator.rb
|
404
417
|
- lib/splitclient-rb/engine/parser/partition.rb
|
405
418
|
- lib/splitclient-rb/engine/push_manager.rb
|
419
|
+
- lib/splitclient-rb/engine/status_manager.rb
|
406
420
|
- lib/splitclient-rb/engine/sync_manager.rb
|
407
421
|
- lib/splitclient-rb/engine/synchronizer.rb
|
408
422
|
- lib/splitclient-rb/exceptions.rb
|
@@ -446,7 +460,6 @@ files:
|
|
446
460
|
- lib/splitclient-rb/utilitites.rb
|
447
461
|
- lib/splitclient-rb/validators.rb
|
448
462
|
- lib/splitclient-rb/version.rb
|
449
|
-
- sonar-scanner.sh
|
450
463
|
- splitclient-rb.gemspec
|
451
464
|
- tasks/benchmark_get_treatment.rake
|
452
465
|
- tasks/irb.rake
|
data/.travis.yml
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
|
3
|
-
rvm:
|
4
|
-
- "2.3.6"
|
5
|
-
|
6
|
-
services:
|
7
|
-
- redis-server
|
8
|
-
|
9
|
-
addons:
|
10
|
-
sonarqube: true
|
11
|
-
|
12
|
-
git:
|
13
|
-
depth: false
|
14
|
-
|
15
|
-
before_install:
|
16
|
-
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
17
|
-
- gem install bundler -v '< 2'
|
18
|
-
|
19
|
-
after_success:
|
20
|
-
- bash sonar-scanner.sh
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
require 'timeout'
|
3
|
-
|
4
|
-
module SplitIoClient
|
5
|
-
module Cache
|
6
|
-
module Stores
|
7
|
-
class SDKBlocker
|
8
|
-
attr_reader :splits_repository
|
9
|
-
|
10
|
-
def initialize(splits_repository, segments_repository, config)
|
11
|
-
@splits_repository = splits_repository
|
12
|
-
@segments_repository = segments_repository
|
13
|
-
@config = config
|
14
|
-
@internal_ready = Concurrent::CountDownLatch.new(1)
|
15
|
-
|
16
|
-
if @config.standalone?
|
17
|
-
@splits_repository.not_ready!
|
18
|
-
@segments_repository.not_ready!
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def splits_ready!
|
23
|
-
if !ready?
|
24
|
-
@splits_repository.ready!
|
25
|
-
@config.logger.info('splits are ready')
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def segments_ready!
|
30
|
-
if !ready?
|
31
|
-
@segments_repository.ready!
|
32
|
-
@config.logger.info('segments are ready')
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def block(time = nil)
|
37
|
-
begin
|
38
|
-
timeout = time || @config.block_until_ready
|
39
|
-
Timeout::timeout(timeout) do
|
40
|
-
sleep 0.1 until ready?
|
41
|
-
end
|
42
|
-
rescue Timeout::Error
|
43
|
-
fail SDKBlockerTimeoutExpiredException, 'SDK start up timeout expired'
|
44
|
-
end
|
45
|
-
|
46
|
-
@config.logger.info('SplitIO SDK is ready')
|
47
|
-
end
|
48
|
-
|
49
|
-
def ready?
|
50
|
-
return true if @config.consumer?
|
51
|
-
@splits_repository.ready? && @segments_repository.ready?
|
52
|
-
end
|
53
|
-
|
54
|
-
def sdk_internal_ready
|
55
|
-
@internal_ready.count_down
|
56
|
-
end
|
57
|
-
|
58
|
-
def wait_unitil_internal_ready
|
59
|
-
@internal_ready.wait
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/sonar-scanner.sh
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
#/bin/bash -e
|
2
|
-
|
3
|
-
sonar_scanner() {
|
4
|
-
local params=$@
|
5
|
-
|
6
|
-
sonar-scanner \
|
7
|
-
-Dsonar.host.url='https://sonarqube.split-internal.com' \
|
8
|
-
-Dsonar.login="$SONAR_TOKEN" \
|
9
|
-
-Dsonar.ws.timeout='300' \
|
10
|
-
-Dsonar.sources='lib' \
|
11
|
-
-Dsonar.projectName='ruby-client' \
|
12
|
-
-Dsonar.projectKey='ruby-client' \
|
13
|
-
-Dsonar.ruby.coverage.reportPaths='coverage/.resultset.json' \
|
14
|
-
-Dsonar.links.ci='https://travis-ci.com/splitio/ruby-client' \
|
15
|
-
-Dsonar.links.scm='https://github.com/splitio/ruby-client' \
|
16
|
-
${params}
|
17
|
-
|
18
|
-
return $?
|
19
|
-
}
|
20
|
-
|
21
|
-
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
22
|
-
sonar_scanner \
|
23
|
-
-Dsonar.pullrequest.provider='GitHub' \
|
24
|
-
-Dsonar.pullrequest.github.repository='splitio/ruby-client' \
|
25
|
-
-Dsonar.pullrequest.key=$TRAVIS_PULL_REQUEST \
|
26
|
-
-Dsonar.pullrequest.branch=$TRAVIS_PULL_REQUEST_BRANCH \
|
27
|
-
-Dsonar.pullrequest.base=$TRAVIS_BRANCH
|
28
|
-
else
|
29
|
-
if [ "$TRAVIS_BRANCH" == 'master' ]; then
|
30
|
-
sonar_scanner \
|
31
|
-
-Dsonar.branch.name=$TRAVIS_BRANCH
|
32
|
-
else
|
33
|
-
if [ "$TRAVIS_BRANCH" == 'development' ]; then
|
34
|
-
TARGET_BRANCH='master'
|
35
|
-
else
|
36
|
-
TARGET_BRANCH='development'
|
37
|
-
fi
|
38
|
-
sonar_scanner \
|
39
|
-
-Dsonar.branch.name=$TRAVIS_BRANCH \
|
40
|
-
-Dsonar.branch.target=$TARGET_BRANCH
|
41
|
-
fi
|
42
|
-
fi
|