splitclient-rb 7.0.4.pre.rc3 → 7.1.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -3
  3. data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +4 -0
  4. data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +4 -1
  5. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +1 -1
  6. data/lib/splitclient-rb/clients/split_client.rb +4 -7
  7. data/lib/splitclient-rb/constants.rb +9 -0
  8. data/lib/splitclient-rb/engine/api/splits.rb +0 -1
  9. data/lib/splitclient-rb/engine/auth_api_client.rb +78 -0
  10. data/lib/splitclient-rb/engine/push_manager.rb +46 -0
  11. data/lib/splitclient-rb/engine/sync_manager.rb +112 -0
  12. data/lib/splitclient-rb/engine/synchronizer.rb +80 -0
  13. data/lib/splitclient-rb/exceptions.rb +8 -0
  14. data/lib/splitclient-rb/helpers/thread_helper.rb +19 -0
  15. data/lib/splitclient-rb/split_config.rb +42 -4
  16. data/lib/splitclient-rb/split_factory.rb +25 -15
  17. data/lib/splitclient-rb/sse/event_source/back_off.rb +25 -0
  18. data/lib/splitclient-rb/sse/event_source/client.rb +73 -50
  19. data/lib/splitclient-rb/sse/event_source/stream_data.rb +22 -0
  20. data/lib/splitclient-rb/sse/notification_manager_keeper.rb +45 -0
  21. data/lib/splitclient-rb/sse/notification_processor.rb +50 -0
  22. data/lib/splitclient-rb/sse/sse_handler.rb +46 -50
  23. data/lib/splitclient-rb/sse/workers/control_worker.rb +10 -5
  24. data/lib/splitclient-rb/sse/workers/segments_worker.rb +14 -4
  25. data/lib/splitclient-rb/sse/workers/splits_worker.rb +16 -4
  26. data/lib/splitclient-rb/version.rb +1 -1
  27. data/lib/splitclient-rb.rb +10 -2
  28. data/splitclient-rb.gemspec +1 -0
  29. metadata +26 -4
  30. data/lib/splitclient-rb/engine/parser/split_adapter.rb +0 -105
  31. 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: eafdd083c1f0790ba57e473a7b6fad62f9e142ecfbf7ec07f83a000ab9323756
4
- data.tar.gz: d25fdfe6d2b57d85f3b0a6fd9886fd72c3fe4695193a378c17116a5e26d79eae
3
+ metadata.gz: faa0e8b87fc65523dcfa6611ddb9e672fbd213487aea472455435aa080c29f60
4
+ data.tar.gz: 69b8a67b002dadd9b92e20d04bf18f4a05756ded1822039c48e47ff12a4e20e8
5
5
  SHA512:
6
- metadata.gz: f8e1ac7930d9afc93715329075c4853c5949b8f7cfcaeefb72658b5e02c3c89fdf46ebcde689d7b8071daeb25e5dd9939d7e457c7587f18c8e9f2c1185b342d0
7
- data.tar.gz: 6c9f61e424c8aba6b9c2da31ee7df64fb64b0cb7ad99ff9c4e5c84b9ccaa57e040aa644e1c680a6720247236f3fdf96c6584100f928262ed9ea96d46cb571910
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: 25
5
+ Max: 26
6
6
 
7
7
  Metrics/MethodLength:
8
8
  Max: 20
9
9
 
10
10
  Metrics/ClassLength:
11
- Max: 120
11
+ Max: 140
12
12
 
13
13
  Metrics/LineLength:
14
- Max: 121
14
+ Max: 130
15
15
  Exclude:
16
16
  - spec/sse/**/*
17
17
 
@@ -40,6 +40,10 @@ module SplitIoClient
40
40
  @config.log_found_exception(__method__.to_s, error)
41
41
  end
42
42
 
43
+ def stop_segments_thread
44
+ SplitIoClient::Helpers::ThreadHelper.stop(:segment_fetcher, @config)
45
+ end
46
+
43
47
  private
44
48
 
45
49
  def segments_thread
@@ -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
@@ -133,7 +133,7 @@ module SplitIoClient
133
133
 
134
134
  return if split.nil?
135
135
 
136
- split[:label] = Engine::Models::Label::KILLED
136
+ split[:killed] = true
137
137
  split[:defaultTreatment] = default_treatment
138
138
  split[:changeNumber] = change_number
139
139
 
@@ -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, adapter = nil, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository, sdk_blocker, config, sse_handler)
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
- @adapter.metrics.time('sdk.' + calling_method, latency)
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
- @adapter.metrics.time('sdk.' + calling_method, latency) unless multiple
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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SplitIoClient::Constants
4
+ EXPIRATION_RATE = 600
5
+ CONTROL_PRI = 'control_pri'
6
+ CONTROL_SEC = 'control_sec'
7
+ OCCUPANCY_CHANNEL_PREFIX = '[?occupancy=metrics.publishers]'
8
+ end
9
+
@@ -16,7 +16,6 @@ module SplitIoClient
16
16
  start = Time.now
17
17
 
18
18
  response = get_api("#{@config.base_uri}/splitChanges", @api_key, since: since)
19
-
20
19
  if response.success?
21
20
  result = splits_with_segment_names(response.body)
22
21
 
@@ -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
- @push_notification_enabled = opts[:push_notification_enabled].nil? ? true : false
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 :push_notification_enabled
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
- @adapter = start!
38
+ start!
38
39
 
39
- start_sse!
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
- SplitAdapter.new(@api_key, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @events_repository, @sdk_blocker, @config)
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 start_sse!
122
- if @config.push_notification_enabled
123
- @splits_worker = SSE::Workers::SplitsWorker.new(@adapter, @config, @splits_repository)
124
- @segments_worker = SSE::Workers::SegmentsWorker.new(@adapter, @config, @segments_repository)
125
- @control_worker = SSE::Workers::ControlWorker.new(@adapter, @config)
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
- options = { channels: 'mauro-c', key: 'fake_key', url_host: 'fake-url' }
128
- @sse_handler = SSE::SSEHandler.new(@config, options, @splits_worker, @segments_worker, @control_worker)
129
- end
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