splitclient-rb 7.3.1 → 7.3.2.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +78 -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 +18 -13
- 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 +26 -13
- 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
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03f80e502a07426668e103fece089d2178a8f79b6cd7b99d79fd8832cd75fb41
|
4
|
+
data.tar.gz: 85d9a9d18a4a334581ffad67bdc39ce1d07c10f1d9a6e043f321ceeb9fc33e43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43e4f5b131a63d2c0af3475a49e018d8da1bade5f09aead17025f0cf748612809521e85243dfc7c9c712ba5d8ec31b54117acb14c043c8f6d93650f4a3d9db35
|
7
|
+
data.tar.gz: a1abf9cccb7833173d7e071c70ca216db0476f2fc5e9ae23f4d402a706fd65cfe2712b04771fba19f1bc00b97d3bb07b0f3532279ed66f610c6251715197785c
|
@@ -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 }}
|
@@ -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
|
@@ -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: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
|
-
autorequire:
|
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
|
name: allocation_stats
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.2'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
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
|
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,6 +138,20 @@ dependencies:
|
|
138
138
|
version: 0.59.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: simplecov
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.20.0
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.20.0
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov-json
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
157
|
- - ">="
|
@@ -313,10 +327,10 @@ extensions:
|
|
313
327
|
extra_rdoc_files: []
|
314
328
|
files:
|
315
329
|
- ".github/pull_request_template.md"
|
330
|
+
- ".github/workflows/ci.yml"
|
316
331
|
- ".gitignore"
|
317
332
|
- ".rubocop.yml"
|
318
333
|
- ".simplecov"
|
319
|
-
- ".travis.yml"
|
320
334
|
- Appraisals
|
321
335
|
- CHANGES.txt
|
322
336
|
- CONTRIBUTORS-GUIDE.md
|
@@ -361,7 +375,6 @@ files:
|
|
361
375
|
- lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb
|
362
376
|
- lib/splitclient-rb/cache/stores/localhost_split_builder.rb
|
363
377
|
- lib/splitclient-rb/cache/stores/localhost_split_store.rb
|
364
|
-
- lib/splitclient-rb/cache/stores/sdk_blocker.rb
|
365
378
|
- lib/splitclient-rb/cache/stores/store_utils.rb
|
366
379
|
- lib/splitclient-rb/clients/split_client.rb
|
367
380
|
- lib/splitclient-rb/constants.rb
|
@@ -408,6 +421,7 @@ files:
|
|
408
421
|
- lib/splitclient-rb/engine/parser/evaluator.rb
|
409
422
|
- lib/splitclient-rb/engine/parser/partition.rb
|
410
423
|
- lib/splitclient-rb/engine/push_manager.rb
|
424
|
+
- lib/splitclient-rb/engine/status_manager.rb
|
411
425
|
- lib/splitclient-rb/engine/sync_manager.rb
|
412
426
|
- lib/splitclient-rb/engine/synchronizer.rb
|
413
427
|
- lib/splitclient-rb/exceptions.rb
|
@@ -451,7 +465,6 @@ files:
|
|
451
465
|
- lib/splitclient-rb/utilitites.rb
|
452
466
|
- lib/splitclient-rb/validators.rb
|
453
467
|
- lib/splitclient-rb/version.rb
|
454
|
-
- sonar-scanner.sh
|
455
468
|
- splitclient-rb.gemspec
|
456
469
|
- tasks/benchmark_get_treatment.rake
|
457
470
|
- tasks/irb.rake
|
@@ -459,7 +472,7 @@ homepage: https://github.com/splitio/ruby-client
|
|
459
472
|
licenses:
|
460
473
|
- Apache-2.0
|
461
474
|
metadata: {}
|
462
|
-
post_install_message:
|
475
|
+
post_install_message:
|
463
476
|
rdoc_options: []
|
464
477
|
require_paths:
|
465
478
|
- lib
|
@@ -470,12 +483,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
470
483
|
version: '0'
|
471
484
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
472
485
|
requirements:
|
473
|
-
- - "
|
486
|
+
- - ">"
|
474
487
|
- !ruby/object:Gem::Version
|
475
|
-
version:
|
488
|
+
version: 1.3.1
|
476
489
|
requirements: []
|
477
|
-
rubygems_version: 3.
|
478
|
-
signing_key:
|
490
|
+
rubygems_version: 3.2.32
|
491
|
+
signing_key:
|
479
492
|
specification_version: 4
|
480
493
|
summary: Ruby client for split SDK.
|
481
494
|
test_files: []
|
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
|