splitclient-rb 7.3.0.pre.rc3-java → 7.3.2.pre.rc2-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4ba598e4c83d1357cc014f8635f430b4cdf10618
4
- data.tar.gz: db71590a4c61054f9b3c475a5a5668646787e1ad
3
+ metadata.gz: 16d41224ffaa5d35b5e7b452a2874603466301a2
4
+ data.tar.gz: 88c70650b2948cef0cb93ea00c2453900ae27eee
5
5
  SHA512:
6
- metadata.gz: 2b6c631b7fa5eba6ccb0963353e124d85cca362614488631a783a7915079e341c6991198f302f733b1b3eca33e22c5ecfd64d1029693ddc559cb31bc3b40699f
7
- data.tar.gz: dda52879c7528dc5bd8a911ecce3f35583b836cab397a6559d85c063d6986a9ff151e80350d48425d939b5f1ce9162b7338251ef8799dd72cbf3b8521085ae4a
6
+ metadata.gz: ce93919c5848f7394282caa57dc3dc2ab1a0818ddb4a73be206f5754debe613787c2983314b8f98e54c5bbb4aed0d6bffa3962a043fe907afc6a937a27a20583
7
+ data.tar.gz: 36d929f0894488db664d3b8fecb37e1e0f9f2014bf856edcce89d40ee041943f4e2c92bd82f9e596934314b800db5de4fa766e3d38de558b85ff183cd3b340d7
@@ -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/.rubocop.yml CHANGED
@@ -31,6 +31,7 @@ Metrics/LineLength:
31
31
  - spec/engine/sync_manager_spec.rb
32
32
  - spec/engine/auth_api_client_spec.rb
33
33
  - spec/telemetry/synchronizer_spec.rb
34
+ - spec/splitclient/split_config_spec.rb
34
35
 
35
36
  Style/BracesAroundHashParameters:
36
37
  Exclude:
@@ -62,3 +63,4 @@ AllCops:
62
63
  - lib/splitclient-rb/engine/models/**/*
63
64
  - lib/splitclient-rb/engine/parser/**/*
64
65
  - spec/telemetry/synchronizer_spec.rb
66
+ - lib/splitclient-rb/engine/synchronizer.rb
data/CHANGES.txt CHANGED
@@ -1,5 +1,12 @@
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
+
6
+ 7.3.0 (Jul 12, 2021)
7
+ - Updated SDK telemetry storage, metrics and updater to be more effective and send less often.
8
+ - Fixed high cpu usage when api key is wrong.
9
+
3
10
  7.2.3 (Feb 24, 2021)
4
11
  - Fixed missing segment fetch after an SPLIT_UPDATE.
5
12
  - Updated streaming logic to support multiregion.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2020 Split Software, Inc.
1
+ Copyright © 2021 Split Software, Inc.
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -63,7 +63,7 @@ Split has built and maintains SDKs for:
63
63
  * Java [Github](https://github.com/splitio/java-client) [Docs](https://help.split.io/hc/en-us/articles/360020405151-Java-SDK)
64
64
  * Javascript [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK)
65
65
  * Node [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK)
66
- * .NET [Github](https://github.com/splitio/.net-core-client) [Docs](https://help.split.io/hc/en-us/articles/360020240172--NET-SDK)
66
+ * .NET [Github](https://github.com/splitio/dotnet-client) [Docs](https://help.split.io/hc/en-us/articles/360020240172--NET-SDK)
67
67
  * Ruby [Github](https://github.com/splitio/ruby-client) [Docs](https://help.split.io/hc/en-us/articles/360020673251-Ruby-SDK)
68
68
  * PHP [Github](https://github.com/splitio/php-client) [Docs](https://help.split.io/hc/en-us/articles/360020350372-PHP-SDK)
69
69
  * Python [Github](https://github.com/splitio/python-client) [Docs](https://help.split.io/hc/en-us/articles/360020359652-Python-SDK)
@@ -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, sdk_blocker, telemetry_runtime_producer)
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
@@ -30,16 +29,19 @@ module SplitIoClient
30
29
  def fetch_segments_if_not_exists(names, cache_control_headers = false)
31
30
  names.each do |name|
32
31
  change_number = @segments_repository.get_change_number(name)
33
-
34
- fetch_segment(name, cache_control_headers) if change_number == -1
32
+
33
+ if change_number == -1
34
+ fetch_options = { cache_control_headers: cache_control_headers, till: nil }
35
+ fetch_segment(name, fetch_options) if change_number == -1
36
+ end
35
37
  end
36
38
  rescue StandardError => error
37
39
  @config.log_found_exception(__method__.to_s, error)
38
40
  end
39
41
 
40
- def fetch_segment(name, cache_control_headers = false)
42
+ def fetch_segment(name, fetch_options = { cache_control_headers: false, till: nil })
41
43
  @semaphore.synchronize do
42
- segments_api.fetch_segments_by_names([name], cache_control_headers)
44
+ segments_api.fetch_segments_by_names([name], fetch_options)
43
45
  end
44
46
  rescue StandardError => error
45
47
  @config.log_found_exception(__method__.to_s, error)
@@ -49,11 +51,11 @@ module SplitIoClient
49
51
  @semaphore.synchronize do
50
52
  segments_api.fetch_segments_by_names(@segments_repository.used_segment_names)
51
53
 
52
- @sdk_blocker.segments_ready!
53
- @sdk_blocker.sdk_internal_ready
54
+ true
54
55
  end
55
56
  rescue StandardError => error
56
57
  @config.log_found_exception(__method__.to_s, error)
58
+ false
57
59
  end
58
60
 
59
61
  def stop_segments_thread
@@ -67,11 +69,6 @@ module SplitIoClient
67
69
  @config.logger.info('Starting segments fetcher service') if @config.debug_enabled
68
70
 
69
71
  loop do
70
- unless @sdk_blocker.splits_repository.ready?
71
- sleep 0.2
72
- next
73
- end
74
-
75
72
  fetch_segments
76
73
  @config.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if @config.debug_enabled
77
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, sdk_blocker, telemetry_runtime_producer)
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
@@ -27,9 +26,9 @@ module SplitIoClient
27
26
  end
28
27
  end
29
28
 
30
- def fetch_splits(cache_control_headers = false)
29
+ def fetch_splits(fetch_options = { cache_control_headers: false, till: nil })
31
30
  @semaphore.synchronize do
32
- data = splits_since(@splits_repository.get_change_number, cache_control_headers)
31
+ data = splits_since(@splits_repository.get_change_number, fetch_options)
33
32
 
34
33
  data[:splits] && data[:splits].each do |split|
35
34
  add_split_unless_archived(split)
@@ -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
- @sdk_blocker.splits_ready!
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
@@ -68,8 +65,8 @@ module SplitIoClient
68
65
  end
69
66
  end
70
67
 
71
- def splits_since(since, cache_control_headers = false)
72
- splits_api.since(since, cache_control_headers)
68
+ def splits_since(since, fetch_options = { cache_control_headers: false, till: nil })
69
+ splits_api.since(since, fetch_options)
73
70
  end
74
71
 
75
72
  def add_split_unless_archived(split)
@@ -7,10 +7,10 @@ module SplitIoClient
7
7
  require 'yaml'
8
8
  attr_reader :splits_repository
9
9
 
10
- def initialize(splits_repository, config, sdk_blocker = nil)
10
+ def initialize(splits_repository, config, status_manager = nil)
11
11
  @splits_repository = splits_repository
12
12
  @config = config
13
- @sdk_blocker = sdk_blocker
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 @sdk_blocker
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, sdk_blocker, config, impressions_manager, telemetry_evaluation_producer)
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
- @sdk_blocker = sdk_blocker
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
- @sdk_blocker.block(time) if @sdk_blocker && !@sdk_blocker.ready?
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 @sdk_blocker.ready? if @sdk_blocker
313
+ return @status_manager.ready? if @status_manager
314
314
  true
315
315
  end
316
316
 
@@ -11,13 +11,14 @@ module SplitIoClient
11
11
  @telemetry_runtime_producer = telemetry_runtime_producer
12
12
  end
13
13
 
14
- def fetch_segments_by_names(names, cache_control_headers = false)
14
+ def fetch_segments_by_names(names, fetch_options = { cache_control_headers: false, till: nil })
15
15
  return if names.nil? || names.empty?
16
16
 
17
17
  names.each do |name|
18
18
  since = @segments_repository.get_change_number(name)
19
+
19
20
  loop do
20
- segment = fetch_segment_changes(name, since, cache_control_headers)
21
+ segment = fetch_segment_changes(name, since, fetch_options)
21
22
  @segments_repository.add_to_segment(segment)
22
23
 
23
24
  @config.split_logger.log_if_debug("Segment #{name} fetched before: #{since}, \
@@ -32,9 +33,12 @@ module SplitIoClient
32
33
 
33
34
  private
34
35
 
35
- def fetch_segment_changes(name, since, cache_control_headers = false)
36
+ def fetch_segment_changes(name, since, fetch_options = { cache_control_headers: false, till: nil })
36
37
  start = Time.now
37
- response = get_api("#{@config.base_uri}/segmentChanges/#{name}", @api_key, { since: since }, cache_control_headers)
38
+
39
+ params = { since: since }
40
+ params[:till] = fetch_options[:till] unless fetch_options[:till].nil?
41
+ response = get_api("#{@config.base_uri}/segmentChanges/#{name}", @api_key, params, fetch_options[:cache_control_headers])
38
42
 
39
43
  if response.success?
40
44
  segment = JSON.parse(response.body, symbolize_names: true)
@@ -10,10 +10,12 @@ module SplitIoClient
10
10
  @telemetry_runtime_producer = telemetry_runtime_producer
11
11
  end
12
12
 
13
- def since(since, cache_control_headers = false)
13
+ def since(since, fetch_options = { cache_control_headers: false, till: nil })
14
14
  start = Time.now
15
-
16
- response = get_api("#{@config.base_uri}/splitChanges", @api_key, { since: since }, cache_control_headers)
15
+
16
+ params = { since: since }
17
+ params[:till] = fetch_options[:till] unless fetch_options[:till].nil?
18
+ response = get_api("#{@config.base_uri}/splitChanges", @api_key, params, fetch_options[:cache_control_headers])
17
19
  if response.success?
18
20
  result = splits_with_segment_names(response.body)
19
21
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: false
2
+
3
+ module SplitIoClient
4
+ module Engine
5
+ BACKOFF_MAX_ALLOWED = 1.8
6
+ class BackOff
7
+ def initialize(back_off_base, attempt = 0, max_allowed = BACKOFF_MAX_ALLOWED)
8
+ @attempt = attempt
9
+ @back_off_base = back_off_base
10
+ @max_allowed = max_allowed
11
+ end
12
+
13
+ def interval
14
+ interval = 0
15
+ interval = (@back_off_base * (2**@attempt)) if @attempt.positive?
16
+ @attempt += 1
17
+
18
+ interval >= @max_allowed ? @max_allowed : interval
19
+ end
20
+
21
+ def reset
22
+ @attempt = 0
23
+ end
24
+ end
25
+ end
26
+ end
@@ -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 => error
25
- @config.log_found_exception(__method__.to_s, error)
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 => error
52
- @config.log_found_exception(__method__.to_s, error)
51
+ rescue StandardError => e
52
+ @config.log_found_exception(__method__.to_s, e)
53
53
  end
54
54
 
55
55
  private
@@ -8,7 +8,7 @@ module SplitIoClient
8
8
  @sse_handler = sse_handler
9
9
  @auth_api_client = AuthApiClient.new(@config, telemetry_runtime_producer)
10
10
  @api_key = api_key
11
- @back_off = SplitIoClient::SSE::EventSource::BackOff.new(@config.auth_retry_back_off_base, 1)
11
+ @back_off = Engine::BackOff.new(@config.auth_retry_back_off_base, 1)
12
12
  @telemetry_runtime_producer = telemetry_runtime_producer
13
13
  end
14
14
 
@@ -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
- sdk_blocker,
16
- telemetry_synchronizer
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
- if @config.streaming_enabled
42
- start_stream
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
- synchronize_telemetry_config
49
- end
44
+ @status_manager.ready!
45
+ @telemetry_synchronizer.synchronize_config
46
+ @synchronizer.start_periodic_data_recording
47
+ connected = false
50
48
 
51
- private
52
-
53
- # Starts tasks if stream is enabled.
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
- def start_poll
63
- @config.logger.debug('Starting polling mode ...')
64
- @synchronizer.start_periodic_fetch
65
- @synchronizer.start_periodic_data_recording
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
- # Starts thread which connect to sse and after that fetch splits and segments once.
72
- def start_sse_connection_thread
73
- @config.threads[:sync_manager_start_sse] = Thread.new do
74
- begin
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
- def start_stream_forked
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 synchronize_telemetry_config
169
- @config.threads[:telemetry_config_sender] = Thread.new do
170
- begin
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
@@ -6,13 +6,14 @@ module SplitIoClient
6
6
  include SplitIoClient::Cache::Fetchers
7
7
  include SplitIoClient::Cache::Senders
8
8
 
9
- FORCE_CACHE_CONTROL_HEADERS = true
9
+ ON_DEMAND_FETCH_BACKOFF_BASE_SECONDS = 10
10
+ ON_DEMAND_FETCH_BACKOFF_MAX_WAIT_SECONDS = 60
11
+ ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES = 10
10
12
 
11
13
  def initialize(
12
14
  repositories,
13
15
  api_key,
14
16
  config,
15
- sdk_blocker,
16
17
  params
17
18
  )
18
19
  @splits_repository = repositories[:splits]
@@ -21,7 +22,6 @@ module SplitIoClient
21
22
  @events_repository = repositories[:events]
22
23
  @api_key = api_key
23
24
  @config = config
24
- @sdk_blocker = sdk_blocker
25
25
  @split_fetcher = params[:split_fetcher]
26
26
  @segment_fetcher = params[:segment_fetcher]
27
27
  @impressions_api = SplitIoClient::Api::Impressions.new(@api_key, @config, params[:telemetry_runtime_producer])
@@ -29,12 +29,16 @@ module SplitIoClient
29
29
  @telemetry_synchronizer = params[:telemetry_synchronizer]
30
30
  end
31
31
 
32
- def sync_all
32
+ def sync_all(asynchronous = true)
33
+ unless asynchronous
34
+ return sync_splits_and_segments
35
+ end
36
+
33
37
  @config.threads[:sync_all_thread] = Thread.new do
34
- @config.logger.debug('Synchronizing Splits and Segments ...') if @config.debug_enabled
35
- @split_fetcher.fetch_splits
36
- @segment_fetcher.fetch_segments
38
+ sync_splits_and_segments
37
39
  end
40
+
41
+ true
38
42
  end
39
43
 
40
44
  def start_periodic_data_recording
@@ -54,19 +58,114 @@ module SplitIoClient
54
58
  @segment_fetcher.stop_segments_thread
55
59
  end
56
60
 
57
- def fetch_splits
58
- segment_names = @split_fetcher.fetch_splits(FORCE_CACHE_CONTROL_HEADERS)
59
- @segment_fetcher.fetch_segments_if_not_exists(segment_names, FORCE_CACHE_CONTROL_HEADERS) unless segment_names.empty?
61
+ def fetch_splits(target_change_number)
62
+ return if target_change_number <= @splits_repository.get_change_number.to_i
63
+
64
+ fetch_options = { cache_control_headers: true, till: nil }
65
+
66
+ result = attempt_splits_sync(target_change_number,
67
+ fetch_options,
68
+ @config.on_demand_fetch_max_retries,
69
+ @config.on_demand_fetch_retry_delay_seconds,
70
+ false)
71
+
72
+ attempts = @config.on_demand_fetch_max_retries - result[:remaining_attempts]
73
+ if result[:success]
74
+ @segment_fetcher.fetch_segments_if_not_exists(result[:segment_names], true) unless result[:segment_names].empty?
75
+ @config.logger.debug("Refresh completed in #{attempts} attempts.") if @config.debug_enabled
76
+
77
+ return
78
+ end
79
+
80
+ fetch_options[:till] = target_change_number
81
+ result = attempt_splits_sync(target_change_number,
82
+ fetch_options,
83
+ ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES,
84
+ nil,
85
+ true)
86
+
87
+ attempts = ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES - result[:remaining_attempts]
88
+
89
+ if result[:success]
90
+ @segment_fetcher.fetch_segments_if_not_exists(result[:segment_names], true) unless result[:segment_names].empty?
91
+ @config.logger.debug("Refresh completed bypassing the CDN in #{attempts} attempts.") if @config.debug_enabled
92
+ else
93
+ @config.logger.debug("No changes fetched after #{attempts} attempts with CDN bypassed.") if @config.debug_enabled
94
+ end
95
+ rescue StandardError => error
96
+ @config.log_found_exception(__method__.to_s, error)
60
97
  end
61
98
 
62
- def fetch_segment(name)
63
- @segment_fetcher.fetch_segment(name, FORCE_CACHE_CONTROL_HEADERS)
99
+ def fetch_segment(name, target_change_number)
100
+ return if target_change_number <= @segments_repository.get_change_number(name).to_i
101
+
102
+ fetch_options = { cache_control_headers: true, till: nil }
103
+ result = attempt_segment_sync(name,
104
+ target_change_number,
105
+ fetch_options,
106
+ @config.on_demand_fetch_max_retries,
107
+ @config.on_demand_fetch_retry_delay_seconds,
108
+ false)
109
+
110
+ attempts = @config.on_demand_fetch_max_retries - result[:remaining_attempts]
111
+ if result[:success]
112
+ @config.logger.debug("Segment #{name} refresh completed in #{attempts} attempts.") if @config.debug_enabled
113
+
114
+ return
115
+ end
116
+
117
+ fetch_options = { cache_control_headers: true, till: target_change_number }
118
+ result = attempt_segment_sync(name,
119
+ target_change_number,
120
+ fetch_options,
121
+ ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES,
122
+ nil,
123
+ true)
124
+
125
+ attempts = @config.on_demand_fetch_max_retries - result[:remaining_attempts]
126
+ if result[:success]
127
+ @config.logger.debug("Segment #{name} refresh completed bypassing the CDN in #{attempts} attempts.") if @config.debug_enabled
128
+ else
129
+ @config.logger.debug("No changes fetched for segment #{name} after #{attempts} attempts with CDN bypassed.") if @config.debug_enabled
130
+ end
131
+ rescue StandardError => error
132
+ @config.log_found_exception(__method__.to_s, error)
64
133
  end
65
134
 
66
135
  private
67
136
 
68
- def fetch_segments
69
- @segment_fetcher.fetch_segments
137
+ def attempt_segment_sync(name, target_cn, fetch_options, max_retries, retry_delay_seconds, with_backoff)
138
+ remaining_attempts = max_retries
139
+ backoff = Engine::BackOff.new(ON_DEMAND_FETCH_BACKOFF_BASE_SECONDS, 0, ON_DEMAND_FETCH_BACKOFF_MAX_WAIT_SECONDS) if with_backoff
140
+
141
+ loop do
142
+ remaining_attempts -= 1
143
+
144
+ @segment_fetcher.fetch_segment(name, fetch_options)
145
+
146
+ return sync_result(true, remaining_attempts) if target_cn <= @segments_repository.get_change_number(name).to_i
147
+ return sync_result(false, remaining_attempts) if remaining_attempts <= 0
148
+
149
+ delay = with_backoff ? backoff.interval : retry_delay_seconds
150
+ sleep(delay)
151
+ end
152
+ end
153
+
154
+ def attempt_splits_sync(target_cn, fetch_options, max_retries, retry_delay_seconds, with_backoff)
155
+ remaining_attempts = max_retries
156
+ backoff = Engine::BackOff.new(ON_DEMAND_FETCH_BACKOFF_BASE_SECONDS, 0, ON_DEMAND_FETCH_BACKOFF_MAX_WAIT_SECONDS) if with_backoff
157
+
158
+ loop do
159
+ remaining_attempts -= 1
160
+
161
+ result = @split_fetcher.fetch_splits(fetch_options)
162
+
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
165
+
166
+ delay = with_backoff ? backoff.interval : retry_delay_seconds
167
+ sleep(delay)
168
+ end
70
169
  end
71
170
 
72
171
  # Starts thread which loops constantly and sends impressions to the Split API
@@ -87,6 +186,17 @@ module SplitIoClient
87
186
  def start_telemetry_sync_task
88
187
  Telemetry::SyncTask.new(@config, @telemetry_synchronizer).call
89
188
  end
189
+
190
+ def sync_result(success, remaining_attempts, segment_names = nil)
191
+ { success: success, remaining_attempts: remaining_attempts, segment_names: segment_names }
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
90
200
  end
91
201
  end
92
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, sdk_blocker, config)
7
+ def initialize(splits_repository = nil, status_manager, config)
8
8
  @splits_repository = splits_repository
9
- @sdk_blocker = sdk_blocker
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
- @sdk_blocker.block(time) if @sdk_blocker && !@sdk_blocker.ready?
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 @sdk_blocker.ready? if @sdk_blocker
114
+ return @status_manager.ready? if @status_manager
115
115
  true
116
116
  end
117
117
  end
@@ -113,6 +113,9 @@ module SplitIoClient
113
113
 
114
114
  @sdk_start_time = Time.now
115
115
 
116
+ @on_demand_fetch_retry_delay_seconds = SplitConfig.default_on_demand_fetch_retry_delay_seconds
117
+ @on_demand_fetch_max_retries = SplitConfig.default_on_demand_fetch_max_retries
118
+
116
119
  startup_log
117
120
  end
118
121
 
@@ -278,6 +281,17 @@ module SplitIoClient
278
281
 
279
282
  attr_accessor :sdk_start_time
280
283
 
284
+ attr_accessor :on_demand_fetch_retry_delay_seconds
285
+ attr_accessor :on_demand_fetch_max_retries
286
+
287
+ def self.default_on_demand_fetch_retry_delay_seconds
288
+ 0.05
289
+ end
290
+
291
+ def self.default_on_demand_fetch_max_retries
292
+ 10
293
+ end
294
+
281
295
  def self.default_impressions_mode
282
296
  :optimized
283
297
  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, @sdk_blocker, @config, @impressions_manager, @evaluation_producer)
46
- @manager = SplitManager.new(@splits_repository, @sdk_blocker, @config)
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
- start_localhost_components
56
- else
57
- split_fetcher = SplitFetcher.new(@splits_repository, @api_key, config, @sdk_blocker, @runtime_producer)
58
- segment_fetcher = SegmentFetcher.new(@segments_repository, @api_key, config, @sdk_blocker, @runtime_producer)
59
- params = {
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
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, @sdk_blocker).call
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
@@ -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)
@@ -51,11 +51,7 @@ module SplitIoClient
51
51
  cn = item[:change_number]
52
52
  @config.logger.debug("SegmentsWorker change_number dequeue #{segment_name}, #{cn}")
53
53
 
54
- attempt = 0
55
- while cn > @segments_repository.get_change_number(segment_name).to_i && attempt <= Workers::MAX_RETRIES_ALLOWED
56
- @synchronizer.fetch_segment(segment_name)
57
- attempt += 1
58
- end
54
+ @synchronizer.fetch_segment(segment_name, cn)
59
55
  end
60
56
  end
61
57
 
@@ -3,8 +3,6 @@
3
3
  module SplitIoClient
4
4
  module SSE
5
5
  module Workers
6
- MAX_RETRIES_ALLOWED = 10
7
-
8
6
  class SplitsWorker
9
7
  def initialize(synchronizer, config, splits_repository)
10
8
  @synchronizer = synchronizer
@@ -62,12 +60,7 @@ module SplitIoClient
62
60
  def perform
63
61
  while (change_number = @queue.pop)
64
62
  @config.logger.debug("SplitsWorker change_number dequeue #{change_number}")
65
-
66
- attempt = 0
67
- while change_number > @splits_repository.get_change_number.to_i && attempt <= Workers::MAX_RETRIES_ALLOWED
68
- @synchronizer.fetch_splits
69
- attempt += 1
70
- end
63
+ @synchronizer.fetch_splits(change_number)
71
64
  end
72
65
  end
73
66
 
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '7.3.0.pre.rc3'
2
+ VERSION = '7.3.2.pre.rc2'
3
3
  end
@@ -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'
@@ -85,13 +84,14 @@ require 'splitclient-rb/engine/models/split'
85
84
  require 'splitclient-rb/engine/models/label'
86
85
  require 'splitclient-rb/engine/models/treatment'
87
86
  require 'splitclient-rb/engine/auth_api_client'
87
+ require 'splitclient-rb/engine/back_off'
88
88
  require 'splitclient-rb/engine/push_manager'
89
+ require 'splitclient-rb/engine/status_manager'
89
90
  require 'splitclient-rb/engine/sync_manager'
90
91
  require 'splitclient-rb/engine/synchronizer'
91
92
  require 'splitclient-rb/utilitites'
92
93
 
93
- # SSE
94
- require 'splitclient-rb/sse/event_source/back_off'
94
+ # SSE
95
95
  require 'splitclient-rb/sse/event_source/client'
96
96
  require 'splitclient-rb/sse/event_source/event_parser'
97
97
  require 'splitclient-rb/sse/event_source/event_types'
@@ -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', '~> 1.11'
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.0.pre.rc3
4
+ version: 7.3.2.pre.rc2
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-06-25 00:00:00.000000000 Z
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: '1.11'
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: '1.11'
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
@@ -369,6 +382,7 @@ files:
369
382
  - lib/splitclient-rb/engine/api/splits.rb
370
383
  - lib/splitclient-rb/engine/api/telemetry_api.rb
371
384
  - lib/splitclient-rb/engine/auth_api_client.rb
385
+ - lib/splitclient-rb/engine/back_off.rb
372
386
  - lib/splitclient-rb/engine/common/impressions_counter.rb
373
387
  - lib/splitclient-rb/engine/common/impressions_manager.rb
374
388
  - lib/splitclient-rb/engine/evaluator/splitter.rb
@@ -402,6 +416,7 @@ files:
402
416
  - lib/splitclient-rb/engine/parser/evaluator.rb
403
417
  - lib/splitclient-rb/engine/parser/partition.rb
404
418
  - lib/splitclient-rb/engine/push_manager.rb
419
+ - lib/splitclient-rb/engine/status_manager.rb
405
420
  - lib/splitclient-rb/engine/sync_manager.rb
406
421
  - lib/splitclient-rb/engine/synchronizer.rb
407
422
  - lib/splitclient-rb/exceptions.rb
@@ -412,7 +427,6 @@ files:
412
427
  - lib/splitclient-rb/split_factory_builder.rb
413
428
  - lib/splitclient-rb/split_factory_registry.rb
414
429
  - lib/splitclient-rb/split_logger.rb
415
- - lib/splitclient-rb/sse/event_source/back_off.rb
416
430
  - lib/splitclient-rb/sse/event_source/client.rb
417
431
  - lib/splitclient-rb/sse/event_source/event_parser.rb
418
432
  - lib/splitclient-rb/sse/event_source/event_types.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
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: false
2
-
3
- module SplitIoClient
4
- module SSE
5
- module EventSource
6
- class BackOff
7
- def initialize(back_off_base, attempt = 0)
8
- @attempt = attempt
9
- @back_off_base = back_off_base
10
- end
11
-
12
- def interval
13
- interval = (@back_off_base * (2**@attempt)) if @attempt.positive?
14
- @attempt += 1
15
-
16
- interval || 0
17
- end
18
-
19
- def reset
20
- @attempt = 0
21
- end
22
- end
23
- end
24
- end
25
- 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