splitclient-rb 7.0.4.pre.rc3 → 7.1.0.pre.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -3
- data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +4 -0
- data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +4 -1
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +1 -1
- data/lib/splitclient-rb/clients/split_client.rb +4 -7
- data/lib/splitclient-rb/constants.rb +9 -0
- data/lib/splitclient-rb/engine/api/splits.rb +0 -1
- data/lib/splitclient-rb/engine/auth_api_client.rb +78 -0
- data/lib/splitclient-rb/engine/push_manager.rb +46 -0
- data/lib/splitclient-rb/engine/sync_manager.rb +112 -0
- data/lib/splitclient-rb/engine/synchronizer.rb +80 -0
- data/lib/splitclient-rb/exceptions.rb +8 -0
- data/lib/splitclient-rb/helpers/thread_helper.rb +19 -0
- data/lib/splitclient-rb/split_config.rb +42 -4
- data/lib/splitclient-rb/split_factory.rb +25 -15
- data/lib/splitclient-rb/sse/event_source/back_off.rb +25 -0
- data/lib/splitclient-rb/sse/event_source/client.rb +73 -50
- data/lib/splitclient-rb/sse/event_source/stream_data.rb +22 -0
- data/lib/splitclient-rb/sse/notification_manager_keeper.rb +45 -0
- data/lib/splitclient-rb/sse/notification_processor.rb +50 -0
- data/lib/splitclient-rb/sse/sse_handler.rb +46 -50
- data/lib/splitclient-rb/sse/workers/control_worker.rb +10 -5
- data/lib/splitclient-rb/sse/workers/segments_worker.rb +14 -4
- data/lib/splitclient-rb/sse/workers/splits_worker.rb +16 -4
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +10 -2
- data/splitclient-rb.gemspec +1 -0
- metadata +26 -4
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +0 -105
- data/lib/splitclient-rb/sse/event_source/status.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: faa0e8b87fc65523dcfa6611ddb9e672fbd213487aea472455435aa080c29f60
|
4
|
+
data.tar.gz: 69b8a67b002dadd9b92e20d04bf18f4a05756ded1822039c48e47ff12a4e20e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b95e354b732d3377dc4d4bd5daf1b20d05b31e68478cb9e045f9f89b60a04c6834995a1522e7db43e450beeeec0bfb96547408f4f82032c80ad9117b7ac911be
|
7
|
+
data.tar.gz: 573ac96c29360b36f0091992604e3acd970732ca609377f1895776b1750dfc59d5627025c10ad8472c066a5b551fae0df87ff0db17ed3afe817bdfb12f1d42b7
|
data/.rubocop.yml
CHANGED
@@ -2,16 +2,16 @@ Documentation:
|
|
2
2
|
Enabled: false
|
3
3
|
|
4
4
|
Metrics/AbcSize:
|
5
|
-
Max:
|
5
|
+
Max: 26
|
6
6
|
|
7
7
|
Metrics/MethodLength:
|
8
8
|
Max: 20
|
9
9
|
|
10
10
|
Metrics/ClassLength:
|
11
|
-
Max:
|
11
|
+
Max: 140
|
12
12
|
|
13
13
|
Metrics/LineLength:
|
14
|
-
Max:
|
14
|
+
Max: 130
|
15
15
|
Exclude:
|
16
16
|
- spec/sse/**/*
|
17
17
|
|
@@ -39,11 +39,14 @@ module SplitIoClient
|
|
39
39
|
@config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled
|
40
40
|
|
41
41
|
@sdk_blocker.splits_ready!
|
42
|
-
|
43
42
|
rescue StandardError => error
|
44
43
|
@config.log_found_exception(__method__.to_s, error)
|
45
44
|
end
|
46
45
|
|
46
|
+
def stop_splits_thread
|
47
|
+
SplitIoClient::Helpers::ThreadHelper.stop(:split_fetcher, @config)
|
48
|
+
end
|
49
|
+
|
47
50
|
private
|
48
51
|
|
49
52
|
def splits_thread
|
@@ -9,8 +9,9 @@ module SplitIoClient
|
|
9
9
|
# @param api_key [String] the API key for your split account
|
10
10
|
#
|
11
11
|
# @return [SplitIoClient] split.io client instance
|
12
|
-
def initialize(api_key,
|
12
|
+
def initialize(api_key, metrics, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository, sdk_blocker, config)
|
13
13
|
@api_key = api_key
|
14
|
+
@metrics = metrics
|
14
15
|
@splits_repository = splits_repository
|
15
16
|
@segments_repository = segments_repository
|
16
17
|
@impressions_repository = impressions_repository
|
@@ -19,8 +20,6 @@ module SplitIoClient
|
|
19
20
|
@sdk_blocker = sdk_blocker
|
20
21
|
@destroyed = false
|
21
22
|
@config = config
|
22
|
-
@adapter = adapter
|
23
|
-
@sse_handler = sse_handler
|
24
23
|
end
|
25
24
|
|
26
25
|
def get_treatment(
|
@@ -62,8 +61,6 @@ module SplitIoClient
|
|
62
61
|
thread.join
|
63
62
|
end
|
64
63
|
|
65
|
-
@sse_handler.sse_client.close if @config.push_notification_enabled
|
66
|
-
|
67
64
|
@config.threads.values.each { |thread| Thread.kill(thread) }
|
68
65
|
|
69
66
|
@splits_repository.clear
|
@@ -252,7 +249,7 @@ module SplitIoClient
|
|
252
249
|
end
|
253
250
|
latency = (Time.now - start) * 1000.0
|
254
251
|
# Measure
|
255
|
-
@
|
252
|
+
@metrics.time('sdk.' + calling_method, latency)
|
256
253
|
|
257
254
|
treatments_for_impressions = get_treatment_for_impressions(treatments_labels_change_numbers)
|
258
255
|
|
@@ -336,7 +333,7 @@ module SplitIoClient
|
|
336
333
|
store_impression(split_name, matching_key, bucketing_key, treatment_data, attributes) if store_impressions
|
337
334
|
|
338
335
|
# Measure
|
339
|
-
@
|
336
|
+
@metrics.time('sdk.' + calling_method, latency) unless multiple
|
340
337
|
rescue StandardError => error
|
341
338
|
@config.log_found_exception(__method__.to_s, error)
|
342
339
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jwt'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
module SplitIoClient
|
7
|
+
module Engine
|
8
|
+
class AuthApiClient
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
@api_client = SplitIoClient::Api::Client.new(@config)
|
12
|
+
end
|
13
|
+
|
14
|
+
def authenticate(api_key)
|
15
|
+
response = @api_client.get_api(@config.auth_service_url, api_key)
|
16
|
+
|
17
|
+
return process_success(response) if response.success?
|
18
|
+
|
19
|
+
if response.status >= 400 && response.status < 500
|
20
|
+
@config.logger.debug("Problem to connect to: #{@config.auth_service_url}. Response status: #{response.status}")
|
21
|
+
|
22
|
+
return { push_enabled: false, retry: false }
|
23
|
+
end
|
24
|
+
|
25
|
+
@config.logger.debug("Problem to connect to: #{@config.auth_service_url}. Response status: #{response.status}")
|
26
|
+
{ push_enabled: false, retry: true }
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def expiration(token_decoded)
|
32
|
+
exp = token_decoded[0]['exp']
|
33
|
+
|
34
|
+
(exp - SplitIoClient::Constants::EXPIRATION_RATE) - Time.now.getutc.to_i unless exp.nil?
|
35
|
+
rescue StandardError => e
|
36
|
+
@config.logger.error("Error getting token expiration: #{e.inspect}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def channels(token_decoded)
|
40
|
+
capability = token_decoded[0]['x-ably-capability']
|
41
|
+
channels_hash = JSON.parse(capability)
|
42
|
+
channels_string = channels_hash.keys.join(',')
|
43
|
+
channels_string = control_channels(channels_string)
|
44
|
+
@config.logger.debug("Channels #{channels_string}")
|
45
|
+
CGI.escape(channels_string)
|
46
|
+
end
|
47
|
+
|
48
|
+
def decode_token(token)
|
49
|
+
JWT.decode token, nil, false
|
50
|
+
end
|
51
|
+
|
52
|
+
def process_success(response)
|
53
|
+
@config.logger.debug("Success connection to: #{@config.auth_service_url}")
|
54
|
+
|
55
|
+
body_json = JSON.parse(response.body, symbolize_names: true)
|
56
|
+
push_enabled = body_json[:pushEnabled]
|
57
|
+
token = body_json[:token]
|
58
|
+
|
59
|
+
if push_enabled
|
60
|
+
decoded_token = decode_token(token)
|
61
|
+
channels = channels(decoded_token)
|
62
|
+
exp = expiration(decoded_token)
|
63
|
+
end
|
64
|
+
|
65
|
+
{ push_enabled: push_enabled, token: token, channels: channels, exp: exp, retry: false }
|
66
|
+
end
|
67
|
+
|
68
|
+
def control_channels(channels_string)
|
69
|
+
prefix = SplitIoClient::Constants::OCCUPANCY_CHANNEL_PREFIX
|
70
|
+
control_pri = SplitIoClient::Constants::CONTROL_PRI
|
71
|
+
control_sec = SplitIoClient::Constants::CONTROL_SEC
|
72
|
+
channels_string = channels_string.gsub(control_pri, "#{prefix}#{control_pri}")
|
73
|
+
channels_string = channels_string.gsub(control_sec, "#{prefix}#{control_sec}")
|
74
|
+
channels_string
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module Engine
|
5
|
+
class PushManager
|
6
|
+
def initialize(config, sse_handler, api_key)
|
7
|
+
@config = config
|
8
|
+
@sse_handler = sse_handler
|
9
|
+
@auth_api_client = AuthApiClient.new(@config)
|
10
|
+
@api_key = api_key
|
11
|
+
@back_off = SplitIoClient::SSE::EventSource::BackOff.new(@config.auth_retry_back_off_base)
|
12
|
+
end
|
13
|
+
|
14
|
+
def start_sse
|
15
|
+
response = @auth_api_client.authenticate(@api_key)
|
16
|
+
|
17
|
+
if response[:push_enabled]
|
18
|
+
@sse_handler.start(response[:token], response[:channels])
|
19
|
+
schedule_next_token_refresh(response[:exp])
|
20
|
+
@back_off.reset
|
21
|
+
else
|
22
|
+
stop_sse
|
23
|
+
end
|
24
|
+
|
25
|
+
schedule_next_token_refresh(@back_off.interval) if response[:retry]
|
26
|
+
rescue StandardError => e
|
27
|
+
@config.logger.error("start_sse: #{e.inspect}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def stop_sse
|
31
|
+
@sse_handler.process_disconnect if @sse_handler.sse_client.nil?
|
32
|
+
@sse_handler.stop
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def schedule_next_token_refresh(time)
|
38
|
+
@config.threads[:schedule_next_token_refresh] = Thread.new do
|
39
|
+
sleep(time)
|
40
|
+
stop_sse
|
41
|
+
start_sse
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module Engine
|
5
|
+
class SyncManager
|
6
|
+
include SplitIoClient::Cache::Fetchers
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
repositories,
|
10
|
+
api_key,
|
11
|
+
config,
|
12
|
+
sdk_blocker,
|
13
|
+
metrics
|
14
|
+
)
|
15
|
+
split_fetcher = SplitFetcher.new(repositories[:splits], api_key, metrics, config, sdk_blocker)
|
16
|
+
segment_fetcher = SegmentFetcher.new(repositories[:segments], api_key, metrics, config, sdk_blocker)
|
17
|
+
sync_params = { split_fetcher: split_fetcher, segment_fetcher: segment_fetcher }
|
18
|
+
|
19
|
+
@synchronizer = Synchronizer.new(repositories, api_key, config, sdk_blocker, sync_params)
|
20
|
+
notification_manager_keeper = SplitIoClient::SSE::NotificationManagerKeeper.new(config) do |manager|
|
21
|
+
manager.on_occupancy { |publisher_available| process_occupancy(publisher_available) }
|
22
|
+
end
|
23
|
+
@sse_handler = SplitIoClient::SSE::SSEHandler.new(
|
24
|
+
config,
|
25
|
+
@synchronizer,
|
26
|
+
repositories[:splits],
|
27
|
+
repositories[:segments],
|
28
|
+
notification_manager_keeper
|
29
|
+
) do |handler|
|
30
|
+
handler.on_connected { process_connected }
|
31
|
+
handler.on_disconnect { process_disconnect }
|
32
|
+
end
|
33
|
+
|
34
|
+
@push_manager = PushManager.new(config, @sse_handler, api_key)
|
35
|
+
@config = config
|
36
|
+
end
|
37
|
+
|
38
|
+
def start
|
39
|
+
if @config.streaming_enabled
|
40
|
+
start_stream
|
41
|
+
elsif @config.standalone?
|
42
|
+
start_poll
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Starts tasks if stream is enabled.
|
49
|
+
def start_stream
|
50
|
+
stream_start_thread
|
51
|
+
stream_start_thread_forked if defined?(PhusionPassenger)
|
52
|
+
|
53
|
+
stream_start_sse_thread
|
54
|
+
stream_start_sse_thread_forked if defined?(PhusionPassenger)
|
55
|
+
end
|
56
|
+
|
57
|
+
def start_poll
|
58
|
+
@synchronizer.start_periodic_fetch
|
59
|
+
@synchronizer.start_periodic_data_recording
|
60
|
+
rescue StandardError => error
|
61
|
+
@config.logger.error(error)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Starts thread which fetch splits and segments once and trigger task to periodic data recording.
|
65
|
+
def stream_start_thread
|
66
|
+
@config.threads[:sync_manager_start_stream] = Thread.new do
|
67
|
+
begin
|
68
|
+
@synchronizer.sync_all
|
69
|
+
@synchronizer.start_periodic_data_recording
|
70
|
+
rescue StandardError => error
|
71
|
+
@config.logger.error(error)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Starts thread which connect to sse and after that fetch splits and segments once.
|
77
|
+
def stream_start_sse_thread
|
78
|
+
@config.threads[:sync_manager_start_sse] = Thread.new do
|
79
|
+
begin
|
80
|
+
@push_manager.start_sse
|
81
|
+
rescue StandardError => error
|
82
|
+
@config.logger.error(error)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def stream_start_thread_forked
|
88
|
+
PhusionPassenger.on_event(:starting_worker_process) { |forked| stream_start_thread if forked }
|
89
|
+
end
|
90
|
+
|
91
|
+
def stream_start_sse_thread_forked
|
92
|
+
PhusionPassenger.on_event(:starting_worker_process) { |forked| stream_start_sse_thread if forked }
|
93
|
+
end
|
94
|
+
|
95
|
+
def process_connected
|
96
|
+
@synchronizer.stop_periodic_fetch
|
97
|
+
@synchronizer.sync_all
|
98
|
+
@sse_handler.start_workers
|
99
|
+
end
|
100
|
+
|
101
|
+
def process_disconnect
|
102
|
+
@sse_handler.stop_workers
|
103
|
+
@synchronizer.start_periodic_fetch
|
104
|
+
end
|
105
|
+
|
106
|
+
def process_occupancy(publisher_available)
|
107
|
+
process_disconnect unless publisher_available
|
108
|
+
process_connected if publisher_available
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module Engine
|
5
|
+
class Synchronizer
|
6
|
+
include SplitIoClient::Cache::Fetchers
|
7
|
+
include SplitIoClient::Cache::Senders
|
8
|
+
|
9
|
+
def initialize(
|
10
|
+
repositories,
|
11
|
+
api_key,
|
12
|
+
config,
|
13
|
+
sdk_blocker,
|
14
|
+
params
|
15
|
+
)
|
16
|
+
@splits_repository = repositories[:splits]
|
17
|
+
@segments_repository = repositories[:segments]
|
18
|
+
@impressions_repository = repositories[:impressions]
|
19
|
+
@metrics_repository = repositories[:metrics]
|
20
|
+
@events_repository = repositories[:events]
|
21
|
+
@api_key = api_key
|
22
|
+
@config = config
|
23
|
+
@sdk_blocker = sdk_blocker
|
24
|
+
@split_fetcher = params[:split_fetcher]
|
25
|
+
@segment_fetcher = params[:segment_fetcher]
|
26
|
+
end
|
27
|
+
|
28
|
+
def sync_all
|
29
|
+
@config.logger.debug('Synchronizing Splits and Segments ...')
|
30
|
+
fetch_splits
|
31
|
+
fetch_segments
|
32
|
+
end
|
33
|
+
|
34
|
+
def start_periodic_data_recording
|
35
|
+
@metrics_sender = metrics_sender
|
36
|
+
@impressions_sender = impressions_sender
|
37
|
+
@events_sender = events_sender
|
38
|
+
end
|
39
|
+
|
40
|
+
def start_periodic_fetch
|
41
|
+
@split_fetcher.call
|
42
|
+
@segment_fetcher.call
|
43
|
+
end
|
44
|
+
|
45
|
+
def stop_periodic_fetch
|
46
|
+
@split_fetcher.stop_splits_thread
|
47
|
+
@segment_fetcher.stop_segments_thread
|
48
|
+
end
|
49
|
+
|
50
|
+
def fetch_splits
|
51
|
+
@split_fetcher.fetch_splits
|
52
|
+
end
|
53
|
+
|
54
|
+
def fetch_segment(name)
|
55
|
+
@segment_fetcher.fetch_segment(name)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def fetch_segments
|
61
|
+
@segment_fetcher.fetch_segments
|
62
|
+
end
|
63
|
+
|
64
|
+
# Starts thread which loops constantly and sends impressions to the Split API
|
65
|
+
def impressions_sender
|
66
|
+
ImpressionsSender.new(@impressions_repository, @api_key, @config).call
|
67
|
+
end
|
68
|
+
|
69
|
+
# Starts thread which loops constantly and sends metrics to the Split API
|
70
|
+
def metrics_sender
|
71
|
+
MetricsSender.new(@metrics_repository, @api_key, @config).call
|
72
|
+
end
|
73
|
+
|
74
|
+
# Starts thread which loops constantly and sends events to the Split API
|
75
|
+
def events_sender
|
76
|
+
EventsSender.new(@events_repository, @config).call
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -4,4 +4,12 @@ module SplitIoClient
|
|
4
4
|
class SDKShutdownException < SplitIoError; end
|
5
5
|
|
6
6
|
class SDKBlockerTimeoutExpiredException < SplitIoError; end
|
7
|
+
|
8
|
+
class SSEClientException < SplitIoError
|
9
|
+
attr_reader :event
|
10
|
+
|
11
|
+
def initialize(event)
|
12
|
+
@event = event
|
13
|
+
end
|
14
|
+
end
|
7
15
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module Helpers
|
5
|
+
class ThreadHelper
|
6
|
+
def self.stop(thread_sym, config)
|
7
|
+
thread = config.threads[thread_sym]
|
8
|
+
|
9
|
+
unless thread.nil?
|
10
|
+
config.logger.debug("Stopping #{thread_sym} ...")
|
11
|
+
sleep(0.1) while thread.status == 'run'
|
12
|
+
Thread.kill(thread)
|
13
|
+
end
|
14
|
+
rescue StandardError => error
|
15
|
+
config.logger.error(error.inspect)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -102,7 +102,11 @@ module SplitIoClient
|
|
102
102
|
@split_validator = SplitIoClient::Validators.new(self)
|
103
103
|
@localhost_mode = opts[:localhost_mode]
|
104
104
|
|
105
|
-
@
|
105
|
+
@streaming_enabled = consumer? ? false : (opts[:streaming_enabled].nil? ? SplitConfig.default_streaming_enabled : opts[:streaming_enabled])
|
106
|
+
@streaming_service_url = opts[:streaming_service_url] || SplitConfig.default_streaming_service_url
|
107
|
+
@auth_service_url = opts[:auth_service_url] || SplitConfig.default_auth_service_url
|
108
|
+
@auth_retry_back_off_base = SplitConfig.init_auth_retry_back_off(opts[:auth_retry_back_off_base] || SplitConfig.default_auth_retry_back_off_base)
|
109
|
+
@streaming_reconnect_back_off_base = SplitConfig.init_streaming_reconnect_back_off(opts[:streaming_reconnect_back_off_base] || SplitConfig.default_streaming_reconnect_back_off_base)
|
106
110
|
|
107
111
|
startup_log
|
108
112
|
end
|
@@ -256,7 +260,43 @@ module SplitIoClient
|
|
256
260
|
|
257
261
|
attr_accessor :ip_addresses_enabled
|
258
262
|
|
259
|
-
attr_accessor :
|
263
|
+
attr_accessor :auth_service_url
|
264
|
+
|
265
|
+
attr_accessor :auth_retry_back_off_base
|
266
|
+
|
267
|
+
attr_accessor :streaming_service_url
|
268
|
+
|
269
|
+
attr_accessor :streaming_reconnect_back_off_base
|
270
|
+
|
271
|
+
attr_accessor :streaming_enabled
|
272
|
+
|
273
|
+
def self.default_streaming_enabled
|
274
|
+
true
|
275
|
+
end
|
276
|
+
|
277
|
+
def self.default_streaming_service_url
|
278
|
+
'https://realtime.ably.io/event-stream'
|
279
|
+
end
|
280
|
+
|
281
|
+
def self.default_auth_service_url
|
282
|
+
'https://auth.split-stage.io/api/auth'
|
283
|
+
end
|
284
|
+
|
285
|
+
def self.default_auth_retry_back_off_base
|
286
|
+
1
|
287
|
+
end
|
288
|
+
|
289
|
+
def self.default_streaming_reconnect_back_off_base
|
290
|
+
1
|
291
|
+
end
|
292
|
+
|
293
|
+
def self.init_auth_retry_back_off(auth_retry_back_off)
|
294
|
+
auth_retry_back_off < 1 ? SplitConfig.default_auth_retry_back_off_base : auth_retry_back_off
|
295
|
+
end
|
296
|
+
|
297
|
+
def self.init_streaming_reconnect_back_off(streaming_reconnect_back_off)
|
298
|
+
streaming_reconnect_back_off < 1 ? SplitConfig.default_streaming_reconnect_back_off_base : streaming_reconnect_back_off
|
299
|
+
end
|
260
300
|
|
261
301
|
#
|
262
302
|
# The default split client configuration
|
@@ -385,8 +425,6 @@ module SplitIoClient
|
|
385
425
|
end
|
386
426
|
end
|
387
427
|
|
388
|
-
|
389
|
-
|
390
428
|
#
|
391
429
|
# The default debug value
|
392
430
|
#
|
@@ -6,6 +6,7 @@ module SplitIoClient
|
|
6
6
|
|
7
7
|
include SplitIoClient::Cache::Repositories
|
8
8
|
include SplitIoClient::Cache::Stores
|
9
|
+
include SplitIoClient::Cache::Senders
|
9
10
|
|
10
11
|
attr_reader :adapter, :client, :manager, :config
|
11
12
|
|
@@ -29,16 +30,14 @@ module SplitIoClient
|
|
29
30
|
@splits_repository = SplitsRepository.new(@config)
|
30
31
|
@segments_repository = SegmentsRepository.new(@config)
|
31
32
|
@impressions_repository = ImpressionsRepository.new(@config)
|
32
|
-
@metrics_repository = MetricsRepository.new(@config)
|
33
33
|
@events_repository = EventsRepository.new(@config, @api_key)
|
34
|
-
|
34
|
+
@metrics_repository = MetricsRepository.new(@config)
|
35
35
|
@sdk_blocker = SDKBlocker.new(@splits_repository, @segments_repository, @config)
|
36
|
+
@metrics = Metrics.new(100, @metrics_repository)
|
36
37
|
|
37
|
-
|
38
|
+
start!
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
@client = SplitClient.new(@api_key, @adapter, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @events_repository, @sdk_blocker, @config, @sse_handler)
|
40
|
+
@client = SplitClient.new(@api_key, @metrics, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @events_repository, @sdk_blocker, @config)
|
42
41
|
@manager = SplitManager.new(@splits_repository, @sdk_blocker, @config)
|
43
42
|
|
44
43
|
validate_api_key
|
@@ -49,7 +48,11 @@ module SplitIoClient
|
|
49
48
|
end
|
50
49
|
|
51
50
|
def start!
|
52
|
-
|
51
|
+
if @config.localhost_mode
|
52
|
+
start_localhost_components
|
53
|
+
else
|
54
|
+
SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, @sdk_blocker, @metrics).start
|
55
|
+
end
|
53
56
|
end
|
54
57
|
|
55
58
|
def stop!
|
@@ -118,15 +121,22 @@ module SplitIoClient
|
|
118
121
|
end
|
119
122
|
end
|
120
123
|
|
121
|
-
def
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
124
|
+
def repositories
|
125
|
+
repos = {}
|
126
|
+
repos[:splits] = @splits_repository
|
127
|
+
repos[:segments] = @segments_repository
|
128
|
+
repos[:impressions] = @impressions_repository
|
129
|
+
repos[:events] = @events_repository
|
130
|
+
repos[:metrics] = @metrics_repository
|
126
131
|
|
127
|
-
|
128
|
-
|
129
|
-
|
132
|
+
repos
|
133
|
+
end
|
134
|
+
|
135
|
+
def start_localhost_components
|
136
|
+
LocalhostSplitStore.new(@splits_repository, @config, @sdk_blocker).call
|
137
|
+
|
138
|
+
# Starts thread which loops constantly and cleans up repositories to avoid memory issues in localhost mode
|
139
|
+
LocalhostRepoCleaner.new(@impressions_repository, @metrics_repository, @events_repository, @config).call
|
130
140
|
end
|
131
141
|
end
|
132
142
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module SSE
|
5
|
+
module EventSource
|
6
|
+
class BackOff
|
7
|
+
def initialize(back_off_base)
|
8
|
+
@attempt = 0
|
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
|