splitclient-rb 7.2.1.pre.rc1 → 7.2.3.pre.rc2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74fed6d315c6504255ab4b6ee3f36c5abda04d1d0b0a18b00b37ceca4afc9624
4
- data.tar.gz: dfcfd4c2f8d02a8e59bc4f12cfbc3c615dc8480b8070e6c3334c3c1940da522c
3
+ metadata.gz: 816703e29d94e1cd110cb01dfd74d4acaa8ba86b0c30306c4e54469e73d1ef42
4
+ data.tar.gz: be893e8e6c83976ddffcbbcd8cadee0c237ec8cbd8a346d3124213f54ab883d8
5
5
  SHA512:
6
- metadata.gz: b28e3518d8174eef454b180747dcfc4afb72c8984b5eef88fb3708607359d2dfed819e47b87360d01b8fa870c5b8f52f3738db72b42c98c15333ca396816488c
7
- data.tar.gz: 82bd3667d880c90f049308e68df73924dcf80306490b5fda7d08d974714f96298cb1ed11f314dc2d028e0acc4c5b05a4981822998a0bb35229ec8981a6bd3536
6
+ metadata.gz: 5924df50b100425b81950f8e7720752e73544dcfea0cda0f8e626075bc3998cf49e3ae1cc140288db247d5a6f5008f068e1f23a40a3335779e0003b70eab4a8c
7
+ data.tar.gz: 0d197320d80ececb3d7b1f70cdf2b1f1eae62ee77f7cb6887082070bcc16332ebf426f3c884c086cdcc9a70e85e4028b2fc1032cf45ae5f3ca89be62d408b1f5
data/.rubocop.yml CHANGED
@@ -10,6 +10,9 @@ Metrics/MethodLength:
10
10
  Metrics/ClassLength:
11
11
  Max: 150
12
12
 
13
+ Metrics/CyclomaticComplexity:
14
+ Max: 8
15
+
13
16
  Metrics/LineLength:
14
17
  Max: 130
15
18
  Exclude:
data/CHANGES.txt CHANGED
@@ -1,5 +1,8 @@
1
1
  CHANGES
2
2
 
3
+ 7.2.2 (Dec 18, 2020)
4
+ - Fixed issue: undefined local variable or method post_impressions_count
5
+
3
6
  7.2.1 (Oct 23, 2020)
4
7
  - Updated redis dependency to >= 4.2.2.
5
8
  - Updated ably error handling.
@@ -27,14 +27,22 @@ module SplitIoClient
27
27
  end
28
28
  end
29
29
 
30
+ def fetch_segments_if_not_exists(names)
31
+ names.each do |name|
32
+ change_number = @segments_repository.get_change_number(name)
33
+
34
+ fetch_segment(name) if change_number == -1
35
+ end
36
+ rescue StandardError => error
37
+ @config.log_found_exception(__method__.to_s, error)
38
+ end
39
+
30
40
  def fetch_segment(name)
31
41
  @semaphore.synchronize do
32
42
  segments_api.fetch_segments_by_names([name])
33
- true
34
43
  end
35
44
  rescue StandardError => error
36
45
  @config.log_found_exception(__method__.to_s, error)
37
- false
38
46
  end
39
47
 
40
48
  def fetch_segments
@@ -41,11 +41,11 @@ module SplitIoClient
41
41
  @config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled
42
42
 
43
43
  @sdk_blocker.splits_ready!
44
- true
44
+
45
+ data[:segment_names]
45
46
  end
46
47
  rescue StandardError => error
47
48
  @config.log_found_exception(__method__.to_s, error)
48
- false
49
49
  end
50
50
 
51
51
  def stop_splits_thread
@@ -40,32 +40,32 @@ module SplitIoClient
40
40
  @config.logger.info('Posting impressions count due to shutdown')
41
41
  end
42
42
  end
43
+ end
43
44
 
44
- def post_impressions_count
45
- @impressions_api.post_count(formatter(@impression_counter.pop_all))
46
- rescue StandardError => error
47
- @config.log_found_exception(__method__.to_s, error)
48
- end
49
-
50
- def formatter(counts)
51
- return if counts.empty?
45
+ def post_impressions_count
46
+ @impressions_api.post_count(formatter(@impression_counter.pop_all))
47
+ rescue StandardError => error
48
+ @config.log_found_exception(__method__.to_s, error)
49
+ end
52
50
 
53
- formated_counts = {pf: []}
51
+ def formatter(counts)
52
+ return if counts.empty?
54
53
 
55
- counts.each do |key, value|
56
- key_splited = key.split('::')
57
-
58
- formated_counts[:pf] << {
59
- f: key_splited[0].to_s, # feature name
60
- m: key_splited[1].to_i, # time frame
61
- rc: value # count
62
- }
63
- end
54
+ formated_counts = {pf: []}
64
55
 
65
- formated_counts
66
- rescue StandardError => error
67
- @config.log_found_exception(__method__.to_s, error)
56
+ counts.each do |key, value|
57
+ key_splited = key.split('::')
58
+
59
+ formated_counts[:pf] << {
60
+ f: key_splited[0].to_s, # feature name
61
+ m: key_splited[1].to_i, # time frame
62
+ rc: value # count
63
+ }
68
64
  end
65
+
66
+ formated_counts
67
+ rescue StandardError => error
68
+ @config.log_found_exception(__method__.to_s, error)
69
69
  end
70
70
  end
71
71
  end
@@ -6,5 +6,10 @@ class SplitIoClient::Constants
6
6
  CONTROL_SEC = 'control_sec'
7
7
  OCCUPANCY_CHANNEL_PREFIX = '[?occupancy=metrics.publishers]'
8
8
  FETCH_BACK_OFF_BASE_RETRIES = 1
9
+ PUSH_CONNECTED = 'PUSH_CONNECTED'
10
+ PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR'
11
+ PUSH_NONRETRYABLE_ERROR = 'PUSH_NONRETRYABLE_ERROR'
12
+ PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN'
13
+ PUSH_SUBSYSTEM_READY = 'PUSH_SUBSYSTEM_READY'
14
+ PUSH_SUBSYSTEM_OFF = 'PUSH_SUBSYSTEM_OFF'
9
15
  end
10
-
@@ -19,12 +19,13 @@ module SplitIoClient
19
19
  if response[:push_enabled] && @sse_handler.start(response[:token], response[:channels])
20
20
  schedule_next_token_refresh(response[:exp])
21
21
  @back_off.reset
22
- return
22
+ return true
23
23
  end
24
24
 
25
25
  stop_sse
26
26
 
27
27
  schedule_next_token_refresh(@back_off.interval) if response[:retry]
28
+ false
28
29
  rescue StandardError => e
29
30
  @config.logger.error("start_sse: #{e.inspect}")
30
31
  end
@@ -11,8 +11,7 @@ module SplitIoClient
11
11
  )
12
12
  @synchronizer = synchronizer
13
13
  notification_manager_keeper = SplitIoClient::SSE::NotificationManagerKeeper.new(config) do |manager|
14
- manager.on_occupancy { |publisher_available| process_occupancy(publisher_available) }
15
- manager.on_push_shutdown { process_push_shutdown }
14
+ manager.on_action { |action| process_action(action) }
16
15
  end
17
16
  @sse_handler = SplitIoClient::SSE::SSEHandler.new(
18
17
  config,
@@ -21,8 +20,7 @@ module SplitIoClient
21
20
  repositories[:segments],
22
21
  notification_manager_keeper
23
22
  ) do |handler|
24
- handler.on_connected { process_connected }
25
- handler.on_disconnect { |reconnect| process_disconnect(reconnect) }
23
+ handler.on_action { |action| process_action(action) }
26
24
  end
27
25
 
28
26
  @push_manager = PushManager.new(config, @sse_handler, api_key)
@@ -44,10 +42,10 @@ module SplitIoClient
44
42
  # Starts tasks if stream is enabled.
45
43
  def start_stream
46
44
  @config.logger.debug('Starting push mode ...')
47
- stream_start_thread
45
+ sync_all_thread
48
46
  @synchronizer.start_periodic_data_recording
49
47
 
50
- stream_start_sse_thread
48
+ start_sse_connection_thread
51
49
  end
52
50
 
53
51
  def start_poll
@@ -59,23 +57,24 @@ module SplitIoClient
59
57
  end
60
58
 
61
59
  # Starts thread which fetch splits and segments once and trigger task to periodic data recording.
62
- def stream_start_thread
60
+ def sync_all_thread
63
61
  @config.threads[:sync_manager_start_stream] = Thread.new do
64
62
  begin
65
63
  @synchronizer.sync_all
66
64
  rescue StandardError => e
67
- @config.logger.error("stream_start_thread error : #{e.inspect}")
65
+ @config.logger.error("sync_all_thread error : #{e.inspect}")
68
66
  end
69
67
  end
70
68
  end
71
69
 
72
70
  # Starts thread which connect to sse and after that fetch splits and segments once.
73
- def stream_start_sse_thread
71
+ def start_sse_connection_thread
74
72
  @config.threads[:sync_manager_start_sse] = Thread.new do
75
73
  begin
76
- @push_manager.start_sse
74
+ connected = @push_manager.start_sse
75
+ @synchronizer.start_periodic_fetch unless connected
77
76
  rescue StandardError => e
78
- @config.logger.error("stream_start_sse_thread error : #{e.inspect}")
77
+ @config.logger.error("start_sse_connection_thread error : #{e.inspect}")
79
78
  end
80
79
  end
81
80
  end
@@ -84,6 +83,46 @@ module SplitIoClient
84
83
  PhusionPassenger.on_event(:starting_worker_process) { |forked| start_stream if forked }
85
84
  end
86
85
 
86
+ def process_action(action)
87
+ case action
88
+ when Constants::PUSH_CONNECTED
89
+ process_connected
90
+ when Constants::PUSH_RETRYABLE_ERROR
91
+ process_disconnect(true)
92
+ when Constants::PUSH_NONRETRYABLE_ERROR
93
+ process_disconnect(false)
94
+ when Constants::PUSH_SUBSYSTEM_DOWN
95
+ process_subsystem_down
96
+ when Constants::PUSH_SUBSYSTEM_READY
97
+ process_subsystem_ready
98
+ when Constants::PUSH_SUBSYSTEM_OFF
99
+ process_push_shutdown
100
+ else
101
+ @config.logger.debug('Incorrect action type.')
102
+ end
103
+ rescue StandardError => e
104
+ @config.logger.error("process_action error: #{e.inspect}")
105
+ end
106
+
107
+ def process_subsystem_ready
108
+ @synchronizer.stop_periodic_fetch
109
+ @synchronizer.sync_all
110
+ @sse_handler.start_workers
111
+ end
112
+
113
+ def process_subsystem_down
114
+ @sse_handler.stop_workers
115
+ @synchronizer.start_periodic_fetch
116
+ end
117
+
118
+ def process_push_shutdown
119
+ @push_manager.stop_sse
120
+ @sse_handler.stop_workers
121
+ @synchronizer.start_periodic_fetch
122
+ rescue StandardError => e
123
+ @config.logger.error("process_push_shutdown error: #{e.inspect}")
124
+ end
125
+
87
126
  def process_connected
88
127
  if @sse_connected.value
89
128
  @config.logger.debug('Streaming already connected.')
@@ -115,28 +154,6 @@ module SplitIoClient
115
154
  rescue StandardError => e
116
155
  @config.logger.error("process_disconnect error: #{e.inspect}")
117
156
  end
118
-
119
- def process_occupancy(push_enable)
120
- if push_enable
121
- @synchronizer.stop_periodic_fetch
122
- @synchronizer.sync_all
123
- @sse_handler.start_workers
124
- return
125
- end
126
-
127
- @sse_handler.stop_workers
128
- @synchronizer.start_periodic_fetch
129
- rescue StandardError => e
130
- @config.logger.error("process_occupancy error: #{e.inspect}")
131
- end
132
-
133
- def process_push_shutdown
134
- @push_manager.stop_sse
135
- @sse_handler.stop_workers
136
- @synchronizer.start_periodic_fetch
137
- rescue StandardError => e
138
- @config.logger.error("process_push_shutdown error: #{e.inspect}")
139
- end
140
157
  end
141
158
  end
142
159
  end
@@ -30,7 +30,7 @@ module SplitIoClient
30
30
  def sync_all
31
31
  @config.threads[:sync_all_thread] = Thread.new do
32
32
  @config.logger.debug('Synchronizing Splits and Segments ...') if @config.debug_enabled
33
- fetch_splits
33
+ @split_fetcher.fetch_splits
34
34
  fetch_segments
35
35
  end
36
36
  end
@@ -53,21 +53,12 @@ module SplitIoClient
53
53
  end
54
54
 
55
55
  def fetch_splits
56
- back_off = SplitIoClient::SSE::EventSource::BackOff.new(SplitIoClient::Constants::FETCH_BACK_OFF_BASE_RETRIES, 1)
57
- loop do
58
- break if @split_fetcher.fetch_splits
59
-
60
- sleep(back_off.interval)
61
- end
56
+ segment_names = @split_fetcher.fetch_splits
57
+ @segment_fetcher.fetch_segments_if_not_exists(segment_names) unless segment_names.empty?
62
58
  end
63
59
 
64
60
  def fetch_segment(name)
65
- back_off = SplitIoClient::SSE::EventSource::BackOff.new(SplitIoClient::Constants::FETCH_BACK_OFF_BASE_RETRIES, 1)
66
- loop do
67
- break if @segment_fetcher.fetch_segment(name)
68
-
69
- sleep(back_off.interval)
70
- end
61
+ @segment_fetcher.fetch_segment(name)
71
62
  end
72
63
 
73
64
  private
@@ -9,6 +9,7 @@ module SplitIoClient
9
9
  class Client
10
10
  DEFAULT_READ_TIMEOUT = 70
11
11
  CONNECT_TIMEOUT = 30_000
12
+ OK_CODE = 200
12
13
  KEEP_ALIVE_RESPONSE = "c\r\n:keepalive\n\n\r\n".freeze
13
14
  ERROR_EVENT_TYPE = 'error'.freeze
14
15
 
@@ -16,9 +17,10 @@ module SplitIoClient
16
17
  @config = config
17
18
  @read_timeout = read_timeout
18
19
  @connected = Concurrent::AtomicBoolean.new(false)
20
+ @first_event = Concurrent::AtomicBoolean.new(true)
19
21
  @socket = nil
20
22
  @event_parser = SSE::EventSource::EventParser.new(config)
21
- @on = { event: ->(_) {}, connected: ->(_) {}, disconnect: ->(_) {} }
23
+ @on = { event: ->(_) {}, action: ->(_) {} }
22
24
 
23
25
  yield self if block_given?
24
26
  end
@@ -27,16 +29,12 @@ module SplitIoClient
27
29
  @on[:event] = action
28
30
  end
29
31
 
30
- def on_connected(&action)
31
- @on[:connected] = action
32
+ def on_action(&action)
33
+ @on[:action] = action
32
34
  end
33
35
 
34
- def on_disconnect(&action)
35
- @on[:disconnect] = action
36
- end
37
-
38
- def close(reconnect = false)
39
- dispatch_disconnect(reconnect)
36
+ def close(action = Constants::PUSH_NONRETRYABLE_ERROR)
37
+ dispatch_action(action)
40
38
  @connected.make_false
41
39
  SplitIoClient::Helpers::ThreadHelper.stop(:connect_stream, @config)
42
40
  @socket&.close
@@ -45,6 +43,11 @@ module SplitIoClient
45
43
  end
46
44
 
47
45
  def start(url)
46
+ if connected?
47
+ @config.logger.debug('SSEClient already running.')
48
+ return true
49
+ end
50
+
48
51
  @uri = URI(url)
49
52
  latch = Concurrent::CountDownLatch.new(1)
50
53
 
@@ -72,16 +75,18 @@ module SplitIoClient
72
75
  end
73
76
 
74
77
  def connect_stream(latch)
75
- socket_write(latch)
78
+ socket_write
76
79
 
77
- while @connected.value
80
+ while connected? || @first_event.value
78
81
  begin
79
82
  partial_data = @socket.readpartial(10_000, timeout: @read_timeout)
80
83
 
84
+ read_first_event(partial_data, latch)
85
+
81
86
  raise 'eof exception' if partial_data == :eof
82
87
  rescue StandardError => e
83
88
  @config.logger.error('Error reading partial data: ' + e.inspect) if @config.debug_enabled
84
- close(true) # close conexion & reconnect
89
+ close(Constants::PUSH_RETRYABLE_ERROR)
85
90
  return
86
91
  end
87
92
 
@@ -89,14 +94,31 @@ module SplitIoClient
89
94
  end
90
95
  end
91
96
 
92
- def socket_write(latch)
97
+ def socket_write
98
+ @first_event.make_true
93
99
  @socket = socket_connect
94
100
  @socket.write(build_request(@uri))
95
- dispatch_connected
96
101
  rescue StandardError => e
97
102
  @config.logger.error("Error during connecting to #{@uri.host}. Error: #{e.inspect}")
98
- close
99
- ensure
103
+ close(Constants::PUSH_NONRETRYABLE_ERROR)
104
+ end
105
+
106
+ def read_first_event(data, latch)
107
+ return unless @first_event.value
108
+
109
+ response_code = @event_parser.first_event(data)
110
+ @config.logger.debug("SSE client first event code: #{response_code}")
111
+
112
+ error_event = false
113
+ events = @event_parser.parse(data)
114
+ events.each { |e| error_event = true if e.event_type == ERROR_EVENT_TYPE }
115
+ @first_event.make_false
116
+
117
+ if response_code == OK_CODE && !error_event
118
+ @connected.make_true
119
+ dispatch_action(Constants::PUSH_CONNECTED)
120
+ end
121
+
100
122
  latch.count_down
101
123
  end
102
124
 
@@ -137,9 +159,9 @@ module SplitIoClient
137
159
  def dispatch_error(event)
138
160
  @config.logger.error("Event error: #{event.event_type}, #{event.data}")
139
161
  if event.data['code'] >= 40_140 && event.data['code'] <= 40_149
140
- close(true) # close conexion & reconnect
162
+ close(Constants::PUSH_RETRYABLE_ERROR)
141
163
  elsif event.data['code'] >= 40_000 && event.data['code'] <= 49_999
142
- close # close conexion
164
+ close(Constants::PUSH_NONRETRYABLE_ERROR)
143
165
  end
144
166
  end
145
167
 
@@ -148,15 +170,9 @@ module SplitIoClient
148
170
  @on[:event].call(event)
149
171
  end
150
172
 
151
- def dispatch_connected
152
- @connected.make_true
153
- @config.logger.debug('Dispatching connected') if @config.debug_enabled
154
- @on[:connected].call
155
- end
156
-
157
- def dispatch_disconnect(reconnect)
158
- @config.logger.debug('Dispatching disconnect') if @config.debug_enabled
159
- @on[:disconnect].call(reconnect)
173
+ def dispatch_action(action)
174
+ @config.logger.debug("Dispatching action: #{action}") if @config.debug_enabled
175
+ @on[:action].call(action)
160
176
  end
161
177
  end
162
178
  end
@@ -4,6 +4,8 @@ module SplitIoClient
4
4
  module SSE
5
5
  module EventSource
6
6
  class EventParser
7
+ BAD_REQUEST_CODE = 400
8
+
7
9
  def initialize(config)
8
10
  @config = config
9
11
  end
@@ -27,10 +29,17 @@ module SplitIoClient
27
29
 
28
30
  events
29
31
  rescue StandardError => e
30
- @config.logger.error("Error during parsing a event: #{e.inspect}")
32
+ @config.logger.debug("Error during parsing a event: #{e.inspect}")
31
33
  []
32
34
  end
33
35
 
36
+ def first_event(raw_data)
37
+ raw_data.split("\n")[0].split(' ')[1].to_i
38
+ rescue StandardError => e
39
+ @config.logger.debug("Error parsing first event: #{e.inspect}")
40
+ BAD_REQUEST_CODE
41
+ end
42
+
34
43
  private
35
44
 
36
45
  def parse_event_data(data, type)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'concurrent/atomics'
3
+ require 'concurrent'
4
4
 
5
5
  module SplitIoClient
6
6
  module SSE
@@ -8,7 +8,9 @@ module SplitIoClient
8
8
  def initialize(config)
9
9
  @config = config
10
10
  @publisher_available = Concurrent::AtomicBoolean.new(true)
11
- @on = { occupancy: ->(_) {}, push_shutdown: ->(_) {} }
11
+ @publishers_pri = Concurrent::AtomicFixnum.new
12
+ @publishers_sec = Concurrent::AtomicFixnum.new
13
+ @on = { action: ->(_) {} }
12
14
 
13
15
  yield self if block_given?
14
16
  end
@@ -16,19 +18,15 @@ module SplitIoClient
16
18
  def handle_incoming_occupancy_event(event)
17
19
  if event.data['type'] == 'CONTROL'
18
20
  process_event_control(event.data['controlType'])
19
- elsif event.channel == SplitIoClient::Constants::CONTROL_PRI
20
- process_event_occupancy(event.data['metrics']['publishers'])
21
+ else
22
+ process_event_occupancy(event.channel, event.data['metrics']['publishers'])
21
23
  end
22
24
  rescue StandardError => e
23
25
  @config.logger.error(e)
24
26
  end
25
27
 
26
- def on_occupancy(&action)
27
- @on[:occupancy] = action
28
- end
29
-
30
- def on_push_shutdown(&action)
31
- @on[:push_shutdown] = action
28
+ def on_action(&action)
29
+ @on[:action] = action
32
30
  end
33
31
 
34
32
  private
@@ -36,35 +34,42 @@ module SplitIoClient
36
34
  def process_event_control(type)
37
35
  case type
38
36
  when 'STREAMING_PAUSED'
39
- dispatch_occupancy_event(false)
37
+ dispatch_action(Constants::PUSH_SUBSYSTEM_DOWN)
40
38
  when 'STREAMING_RESUMED'
41
- dispatch_occupancy_event(true) if @publisher_available.value
39
+ dispatch_action(Constants::PUSH_SUBSYSTEM_READY) if @publisher_available.value
42
40
  when 'STREAMING_DISABLED'
43
- dispatch_push_shutdown
41
+ dispatch_action(Constants::PUSH_SUBSYSTEM_OFF)
44
42
  else
45
43
  @config.logger.error("Incorrect event type: #{incoming_notification}")
46
44
  end
47
45
  end
48
46
 
49
- def process_event_occupancy(publishers)
50
- @config.logger.debug("Occupancy process event with #{publishers} publishers") if @config.debug_enabled
51
- if publishers <= 0 && @publisher_available.value
47
+ def process_event_occupancy(channel, publishers)
48
+ @config.logger.debug("Processed occupancy event with #{publishers} publishers. Channel: #{channel}")
49
+
50
+ update_publishers(channel, publishers)
51
+
52
+ if !are_publishers_available? && @publisher_available.value
52
53
  @publisher_available.make_false
53
- dispatch_occupancy_event(false)
54
- elsif publishers >= 1 && !@publisher_available.value
54
+ dispatch_action(Constants::PUSH_SUBSYSTEM_DOWN)
55
+ elsif are_publishers_available? && !@publisher_available.value
55
56
  @publisher_available.make_true
56
- dispatch_occupancy_event(true)
57
+ dispatch_action(Constants::PUSH_SUBSYSTEM_READY)
57
58
  end
58
59
  end
59
60
 
60
- def dispatch_occupancy_event(push_enable)
61
- @config.logger.debug("Dispatching occupancy event with publisher avaliable: #{push_enable}")
62
- @on[:occupancy].call(push_enable)
61
+ def update_publishers(channel, publishers)
62
+ @publishers_pri.value = publishers if channel == Constants::CONTROL_PRI
63
+ @publishers_sec.value = publishers if channel == Constants::CONTROL_SEC
64
+ end
65
+
66
+ def are_publishers_available?
67
+ @publishers_pri.value.positive? || @publishers_sec.value.positive?
63
68
  end
64
69
 
65
- def dispatch_push_shutdown
66
- @config.logger.debug('Dispatching push shutdown')
67
- @on[:push_shutdown].call
70
+ def dispatch_action(action)
71
+ @config.logger.debug("Dispatching action: #{action}")
72
+ @on[:action].call(action)
68
73
  end
69
74
  end
70
75
  end
@@ -13,11 +13,10 @@ module SplitIoClient
13
13
  @notification_processor = SplitIoClient::SSE::NotificationProcessor.new(config, @splits_worker, @segments_worker)
14
14
  @sse_client = SSE::EventSource::Client.new(@config) do |client|
15
15
  client.on_event { |event| handle_incoming_message(event) }
16
- client.on_connected { process_connected }
17
- client.on_disconnect { |reconnect| process_disconnect(reconnect) }
16
+ client.on_action { |action| process_action(action) }
18
17
  end
19
18
 
20
- @on = { connected: ->(_) {}, disconnect: ->(_) {} }
19
+ @on = { action: ->(_) {} }
21
20
 
22
21
  yield self if block_given?
23
22
  end
@@ -48,22 +47,14 @@ module SplitIoClient
48
47
  @segments_worker.stop
49
48
  end
50
49
 
51
- def on_connected(&action)
52
- @on[:connected] = action
53
- end
54
-
55
- def on_disconnect(&action)
56
- @on[:disconnect] = action
57
- end
58
-
59
- def process_disconnect(reconnect)
60
- @on[:disconnect].call(reconnect)
50
+ def on_action(&action)
51
+ @on[:action] = action
61
52
  end
62
53
 
63
54
  private
64
55
 
65
- def process_connected
66
- @on[:connected].call
56
+ def process_action(action)
57
+ @on[:action].call(action)
67
58
  end
68
59
 
69
60
  def handle_incoming_message(notification)
@@ -48,12 +48,13 @@ module SplitIoClient
48
48
  def perform
49
49
  while (item = @queue.pop)
50
50
  segment_name = item[:segment_name]
51
- change_number = item[:change_number]
52
- since = @segments_repository.get_change_number(segment_name)
51
+ cn = item[:change_number]
52
+ @config.logger.debug("SegmentsWorker change_number dequeue #{segment_name}, #{cn}")
53
53
 
54
- unless since >= change_number
55
- @config.logger.debug("SegmentsWorker fetch_segment with #{since}")
54
+ attempt = 0
55
+ while cn > @segments_repository.get_change_number(segment_name).to_i && attempt <= Workers::MAX_RETRIES_ALLOWED
56
56
  @synchronizer.fetch_segment(segment_name)
57
+ attempt += 1
57
58
  end
58
59
  end
59
60
  end
@@ -3,6 +3,8 @@
3
3
  module SplitIoClient
4
4
  module SSE
5
5
  module Workers
6
+ MAX_RETRIES_ALLOWED = 10
7
+
6
8
  class SplitsWorker
7
9
  def initialize(synchronizer, config, splits_repository)
8
10
  @synchronizer = synchronizer
@@ -59,11 +61,12 @@ module SplitIoClient
59
61
 
60
62
  def perform
61
63
  while (change_number = @queue.pop)
62
- since = @splits_repository.get_change_number
64
+ @config.logger.debug("SplitsWorker change_number dequeue #{change_number}")
63
65
 
64
- unless since.to_i >= change_number
65
- @config.logger.debug("SplitsWorker fetch_splits with #{since}")
66
+ attempt = 0
67
+ while change_number > @splits_repository.get_change_number.to_i && attempt <= Workers::MAX_RETRIES_ALLOWED
66
68
  @synchronizer.fetch_splits
69
+ attempt += 1
67
70
  end
68
71
  end
69
72
  end
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '7.2.1.pre.rc1'
2
+ VERSION = '7.2.3.pre.rc2'
3
3
  end
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.2.1.pre.rc1
4
+ version: 7.2.3.pre.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Split Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-23 00:00:00.000000000 Z
11
+ date: 2021-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allocation_stats