splitclient-rb 7.3.1.pre.rc1-java → 7.3.2.pre.rc1-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 +24 -50
- 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 +18 -20
- data/lib/splitclient-rb/sse/event_source/client.rb +3 -3
- 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: d8e568f9e8d4fdf7375be19b48cc4ac8b24df542
|
4
|
+
data.tar.gz: fe9615e1c67942bdc52af65b71cb626fcfbcb54f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecec530a3b6a0a2536757fb89f0aff10b4d74144dcbbe48a130d41ca4adb007f821915d194759a1c831cf1c0556afacec2531a4800b9d181149ee6880155a24a
|
7
|
+
data.tar.gz: 296370641c6d160a9fa8cef6ce863772416a6a0acd0a9c10528f30c75db412a1560bce79a3f65108d048efd748f057213feaa642aebf16f098bf4ad729991091
|
@@ -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,56 +33,37 @@ 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
|
41
|
+
@config.threads[:start_sdk] = Thread.new do
|
42
|
+
sleep(0.5) until @synchronizer.sync_all(false)
|
47
43
|
|
48
|
-
|
49
|
-
|
44
|
+
@status_manager.ready!
|
45
|
+
@telemetry_synchronizer.synchronize_config
|
46
|
+
@synchronizer.start_periodic_data_recording
|
47
|
+
connected = false
|
50
48
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
def start_stream
|
55
|
-
@config.logger.debug('Starting push mode ...')
|
56
|
-
@synchronizer.sync_all
|
57
|
-
@synchronizer.start_periodic_data_recording
|
58
|
-
|
59
|
-
start_sse_connection_thread
|
60
|
-
end
|
49
|
+
if @config.streaming_enabled
|
50
|
+
@config.logger.debug('Starting Straming mode ...')
|
51
|
+
connected = @push_manager.start_sse
|
61
52
|
|
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
|
53
|
+
if defined?(PhusionPassenger)
|
54
|
+
PhusionPassenger.on_event(:starting_worker_process) { |forked| sse_thread_forked if forked }
|
55
|
+
end
|
56
|
+
end
|
70
57
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
connected = @push_manager.start_sse
|
76
|
-
@synchronizer.start_periodic_fetch unless connected
|
77
|
-
rescue StandardError => e
|
78
|
-
@config.logger.error("start_sse_connection_thread error : #{e.inspect}")
|
58
|
+
unless connected
|
59
|
+
@config.logger.debug('Starting polling mode ...')
|
60
|
+
@synchronizer.start_periodic_fetch
|
61
|
+
record_telemetry(Telemetry::Domain::Constants::SYNC_MODE, SYNC_MODE_POLLING)
|
79
62
|
end
|
80
63
|
end
|
81
64
|
end
|
82
65
|
|
83
|
-
|
84
|
-
PhusionPassenger.on_event(:starting_worker_process) { |forked| start_stream if forked }
|
85
|
-
end
|
66
|
+
private
|
86
67
|
|
87
68
|
def process_action(action)
|
88
69
|
case action
|
@@ -165,16 +146,9 @@ module SplitIoClient
|
|
165
146
|
@telemetry_runtime_producer.record_streaming_event(type, data)
|
166
147
|
end
|
167
148
|
|
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
|
149
|
+
def sse_thread_forked
|
150
|
+
connected = @push_manager.start_sse
|
151
|
+
@synchronizer.start_periodic_fetch unless connected
|
178
152
|
end
|
179
153
|
end
|
180
154
|
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
|
@@ -34,16 +34,16 @@ module SplitIoClient
|
|
34
34
|
@segments_repository = SegmentsRepository.new(@config)
|
35
35
|
@impressions_repository = ImpressionsRepository.new(@config)
|
36
36
|
@events_repository = EventsRepository.new(@config, @api_key, @runtime_producer)
|
37
|
-
@sdk_blocker = SDKBlocker.new(@splits_repository, @segments_repository, @config)
|
38
37
|
@impression_counter = SplitIoClient::Engine::Common::ImpressionCounter.new
|
39
38
|
@impressions_manager = SplitIoClient::Engine::Common::ImpressionManager.new(@config, @impressions_repository, @impression_counter, @runtime_producer)
|
40
39
|
@telemetry_api = SplitIoClient::Api::TelemetryApi.new(@config, @api_key, @runtime_producer)
|
41
40
|
@telemetry_synchronizer = Telemetry::Synchronizer.new(@config, @telemetry_consumers, @init_producer, repositories, @telemetry_api)
|
41
|
+
@status_manager = Engine::StatusManager.new(@config)
|
42
42
|
|
43
43
|
start!
|
44
44
|
|
45
|
-
@client = SplitClient.new(@api_key, repositories, @
|
46
|
-
@manager = SplitManager.new(@splits_repository, @
|
45
|
+
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer)
|
46
|
+
@manager = SplitManager.new(@splits_repository, @status_manager, @config)
|
47
47
|
|
48
48
|
validate_api_key
|
49
49
|
|
@@ -51,22 +51,20 @@ module SplitIoClient
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def start!
|
54
|
-
if @config.localhost_mode
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, synchronizer, @runtime_producer, @sdk_blocker, @telemetry_synchronizer).start
|
69
|
-
end
|
54
|
+
return start_localhost_components if @config.localhost_mode
|
55
|
+
|
56
|
+
split_fetcher = SplitFetcher.new(@splits_repository, @api_key, config, @runtime_producer)
|
57
|
+
segment_fetcher = SegmentFetcher.new(@segments_repository, @api_key, config, @runtime_producer)
|
58
|
+
params = {
|
59
|
+
split_fetcher: split_fetcher,
|
60
|
+
segment_fetcher: segment_fetcher,
|
61
|
+
imp_counter: @impression_counter,
|
62
|
+
telemetry_runtime_producer: @runtime_producer,
|
63
|
+
telemetry_synchronizer: @telemetry_synchronizer
|
64
|
+
}
|
65
|
+
|
66
|
+
synchronizer = SplitIoClient::Engine::Synchronizer.new(repositories, @api_key, @config, params)
|
67
|
+
SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, synchronizer, @runtime_producer, @telemetry_synchronizer, @status_manager).start
|
70
68
|
end
|
71
69
|
|
72
70
|
def stop!
|
@@ -145,7 +143,7 @@ module SplitIoClient
|
|
145
143
|
end
|
146
144
|
|
147
145
|
def start_localhost_components
|
148
|
-
LocalhostSplitStore.new(@splits_repository, @config, @
|
146
|
+
LocalhostSplitStore.new(@splits_repository, @config, @status_manager).call
|
149
147
|
|
150
148
|
# Starts thread which loops constantly and cleans up repositories to avoid memory issues in localhost mode
|
151
149
|
LocalhostRepoCleaner.new(@impressions_repository, @events_repository, @config).call
|
@@ -38,7 +38,6 @@ module SplitIoClient
|
|
38
38
|
def close(action = Constants::PUSH_NONRETRYABLE_ERROR)
|
39
39
|
dispatch_action(action)
|
40
40
|
@connected.make_false
|
41
|
-
SplitIoClient::Helpers::ThreadHelper.stop(:connect_stream, @config)
|
42
41
|
@socket&.close
|
43
42
|
rescue StandardError => e
|
44
43
|
@config.logger.error("SSEClient close Error: #{e.inspect}")
|
@@ -77,7 +76,7 @@ module SplitIoClient
|
|
77
76
|
end
|
78
77
|
|
79
78
|
def connect_stream(latch)
|
80
|
-
socket_write
|
79
|
+
socket_write(latch)
|
81
80
|
|
82
81
|
while connected? || @first_event.value
|
83
82
|
begin
|
@@ -96,13 +95,14 @@ module SplitIoClient
|
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
99
|
-
def socket_write
|
98
|
+
def socket_write(latch)
|
100
99
|
@first_event.make_true
|
101
100
|
@socket = socket_connect
|
102
101
|
@socket.write(build_request(@uri))
|
103
102
|
rescue StandardError => e
|
104
103
|
@config.logger.error("Error during connecting to #{@uri.host}. Error: #{e.inspect}")
|
105
104
|
close(Constants::PUSH_NONRETRYABLE_ERROR)
|
105
|
+
latch.count_down
|
106
106
|
end
|
107
107
|
|
108
108
|
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.rc1
|
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-24 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
|