splitclient-rb 7.1.4.pre.rc19 → 7.2.2.pre.rc1

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: 60c6946b200c0979eb6eedefce813c20b6e3db78424c35540efab92db20be6a7
4
- data.tar.gz: 073435bf9df789975fcc78d6e0075314e377014722de8fd3eac296f261263499
3
+ metadata.gz: 81877bec1b1e46031afd6857b40762023148f8c068a9bbf94f089d477dbe8ee3
4
+ data.tar.gz: 307ada2bc1aa8ebeac5e2f328c9169359e252e634e25f8873073c8202495c9a0
5
5
  SHA512:
6
- metadata.gz: 420e8e14d6225c92cbab6bc4cdda21314ad9482bae315d8ce0049d3b493caed3376da696c08a563b1bc2e588e9ab11133e7dc311772d0ac56485c0599a1c597f
7
- data.tar.gz: 7b8c32b0fe198035538dc00564cad7aae10a7c1a66173c428f8c4004329e4c91255ddfd8cfc4c48aeb8a28b978b2904e35239d0f4cf944bf95b675cfd96a54ee
6
+ metadata.gz: 9c4d7b28d10044bb81f299a904a2468391adba5c1cc2b658ce3b5e2a8aeae7690a9f742909a4995eef56c86918f5922dc06f4c0fb65f636faa3f8c1f5990f593
7
+ data.tar.gz: 29402faab00d6bd7e2b3928e55b3af3b8d6e262662216b371e9b2cc9f1002036b8435dc52ac2f4421d5f0134603551b8154d555dc2291a4f0583e96468f63b79
@@ -1,5 +1,17 @@
1
1
  CHANGES
2
2
 
3
+ 7.2.2 (Dec 18, 2020)
4
+ - Fixed issue: undefined local variable or method post_impressions_count
5
+
6
+ 7.2.1 (Oct 23, 2020)
7
+ - Updated redis dependency to >= 4.2.2.
8
+ - Updated ably error handling.
9
+
10
+ 7.2.0 (Sep 25, 2020)
11
+ - Added deduplication logic for impressions data.
12
+ - Now there are two modes for Impressions when the SDK is in standalone mode, OPTIMIZED (default) that only ships unique impressions and DEBUG for times where you need to send ALL impressions to debug an integration.
13
+ - Impression listener remains unchanged and will still get all impressions.
14
+
3
15
  7.1.3 (Jul 31, 2020)
4
16
  - Updated rake development dependency to ~> 12.3.3.
5
17
 
@@ -101,6 +101,7 @@ require 'splitclient-rb/redis_metrics_fixer'
101
101
  # SSE
102
102
  require 'splitclient-rb/sse/event_source/back_off'
103
103
  require 'splitclient-rb/sse/event_source/client'
104
+ require 'splitclient-rb/sse/event_source/event_parser'
104
105
  require 'splitclient-rb/sse/event_source/event_types'
105
106
  require 'splitclient-rb/sse/event_source/stream_data'
106
107
  require 'splitclient-rb/sse/workers/segments_worker'
@@ -142,7 +142,7 @@ module SplitIoClient
142
142
 
143
143
  # General
144
144
  def exists?(key)
145
- @redis.exists(key)
145
+ @redis.exists?(key)
146
146
  end
147
147
 
148
148
  def delete(key)
@@ -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
@@ -15,14 +15,15 @@ module SplitIoClient
15
15
  response = @auth_api_client.authenticate(@api_key)
16
16
 
17
17
  @config.logger.debug("Auth service response push_enabled: #{response[:push_enabled]}") if @config.debug_enabled
18
- if response[:push_enabled]
19
- @sse_handler.start(response[:token], response[:channels])
18
+
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
- else
23
- stop_sse
22
+ return
24
23
  end
25
24
 
25
+ stop_sse
26
+
26
27
  schedule_next_token_refresh(@back_off.interval) if response[:retry]
27
28
  rescue StandardError => e
28
29
  @config.logger.error("start_sse: #{e.inspect}")
@@ -31,6 +32,7 @@ module SplitIoClient
31
32
  def stop_sse
32
33
  @sse_handler.process_disconnect if @sse_handler.sse_client.nil?
33
34
  @sse_handler.stop
35
+ SplitIoClient::Helpers::ThreadHelper.stop(:schedule_next_token_refresh, @config)
34
36
  end
35
37
 
36
38
  private
@@ -41,7 +43,7 @@ module SplitIoClient
41
43
  @config.logger.debug("schedule_next_token_refresh refresh in #{time} seconds.") if @config.debug_enabled
42
44
  sleep(time)
43
45
  @config.logger.debug('schedule_next_token_refresh starting ...') if @config.debug_enabled
44
- stop_sse
46
+ @sse_handler.stop
45
47
  start_sse
46
48
  rescue StandardError => e
47
49
  @config.logger.debug("schedule_next_token_refresh error: #{e.inspect}") if @config.debug_enabled
@@ -3,19 +3,13 @@
3
3
  module SplitIoClient
4
4
  module Engine
5
5
  class SyncManager
6
- include SplitIoClient::Cache::Fetchers
7
-
8
6
  def initialize(
9
7
  repositories,
10
8
  api_key,
11
9
  config,
12
- params
10
+ synchronizer
13
11
  )
14
- split_fetcher = SplitFetcher.new(repositories[:splits], api_key, params[:metrics], config, params[:sdk_blocker])
15
- segment_fetcher = SegmentFetcher.new(repositories[:segments], api_key, params[:metrics], config, params[:sdk_blocker])
16
- sync_params = { split_fetcher: split_fetcher, segment_fetcher: segment_fetcher, imp_counter: params[:impression_counter] }
17
-
18
- @synchronizer = Synchronizer.new(repositories, api_key, config, params[:sdk_blocker], sync_params)
12
+ @synchronizer = synchronizer
19
13
  notification_manager_keeper = SplitIoClient::SSE::NotificationManagerKeeper.new(config) do |manager|
20
14
  manager.on_occupancy { |publisher_available| process_occupancy(publisher_available) }
21
15
  manager.on_push_shutdown { process_push_shutdown }
@@ -28,10 +22,11 @@ module SplitIoClient
28
22
  notification_manager_keeper
29
23
  ) do |handler|
30
24
  handler.on_connected { process_connected }
31
- handler.on_disconnect { process_disconnect }
25
+ handler.on_disconnect { |reconnect| process_disconnect(reconnect) }
32
26
  end
33
27
 
34
28
  @push_manager = PushManager.new(config, @sse_handler, api_key)
29
+ @sse_connected = Concurrent::AtomicBoolean.new(false)
35
30
  @config = config
36
31
  end
37
32
 
@@ -90,6 +85,12 @@ module SplitIoClient
90
85
  end
91
86
 
92
87
  def process_connected
88
+ if @sse_connected.value
89
+ @config.logger.debug('Streaming already connected.')
90
+ return
91
+ end
92
+
93
+ @sse_connected.make_true
93
94
  @synchronizer.stop_periodic_fetch
94
95
  @synchronizer.sync_all
95
96
  @sse_handler.start_workers
@@ -97,23 +98,42 @@ module SplitIoClient
97
98
  @config.logger.error("process_connected error: #{e.inspect}")
98
99
  end
99
100
 
100
- def process_disconnect
101
+ def process_disconnect(reconnect)
102
+ unless @sse_connected.value
103
+ @config.logger.debug('Streaming already disconnected.')
104
+ return
105
+ end
106
+
107
+ @sse_connected.make_false
101
108
  @sse_handler.stop_workers
102
109
  @synchronizer.start_periodic_fetch
110
+
111
+ if reconnect
112
+ @synchronizer.sync_all
113
+ @push_manager.start_sse
114
+ end
103
115
  rescue StandardError => e
104
116
  @config.logger.error("process_disconnect error: #{e.inspect}")
105
117
  end
106
118
 
107
119
  def process_occupancy(push_enable)
108
- process_disconnect unless push_enable
109
- process_connected if 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
110
129
  rescue StandardError => e
111
130
  @config.logger.error("process_occupancy error: #{e.inspect}")
112
131
  end
113
132
 
114
133
  def process_push_shutdown
115
134
  @push_manager.stop_sse
116
- process_disconnect
135
+ @sse_handler.stop_workers
136
+ @synchronizer.start_periodic_fetch
117
137
  rescue StandardError => e
118
138
  @config.logger.error("process_push_shutdown error: #{e.inspect}")
119
139
  end
@@ -28,9 +28,11 @@ module SplitIoClient
28
28
  end
29
29
 
30
30
  def sync_all
31
- @config.logger.debug('Synchronizing Splits and Segments ...') if @config.debug_enabled
32
- fetch_splits
33
- fetch_segments
31
+ @config.threads[:sync_all_thread] = Thread.new do
32
+ @config.logger.debug('Synchronizing Splits and Segments ...') if @config.debug_enabled
33
+ fetch_splits
34
+ fetch_segments
35
+ end
34
36
  end
35
37
 
36
38
  def start_periodic_data_recording
@@ -7,6 +7,7 @@ module SplitIoClient
7
7
  include SplitIoClient::Cache::Repositories
8
8
  include SplitIoClient::Cache::Stores
9
9
  include SplitIoClient::Cache::Senders
10
+ include SplitIoClient::Cache::Fetchers
10
11
 
11
12
  attr_reader :adapter, :client, :manager, :config
12
13
 
@@ -53,8 +54,12 @@ module SplitIoClient
53
54
  if @config.localhost_mode
54
55
  start_localhost_components
55
56
  else
56
- params = { sdk_blocker: @sdk_blocker, metrics: @metrics, impression_counter: @impression_counter }
57
- SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, params).start
57
+ split_fetcher = SplitFetcher.new(@splits_repository, @api_key, @metrics, config, @sdk_blocker)
58
+ segment_fetcher = SegmentFetcher.new(@segments_repository, @api_key, @metrics, config, @sdk_blocker)
59
+ params = { split_fetcher: split_fetcher, segment_fetcher: segment_fetcher, imp_counter: @impression_counter }
60
+
61
+ synchronizer = SplitIoClient::Engine::Synchronizer.new(repositories, @api_key, @config, @sdk_blocker, params)
62
+ SplitIoClient::Engine::SyncManager.new(repositories, @api_key, @config, synchronizer).start
58
63
  end
59
64
  end
60
65
 
@@ -125,14 +130,13 @@ module SplitIoClient
125
130
  end
126
131
 
127
132
  def repositories
128
- repos = {}
129
- repos[:splits] = @splits_repository
130
- repos[:segments] = @segments_repository
131
- repos[:impressions] = @impressions_repository
132
- repos[:events] = @events_repository
133
- repos[:metrics] = @metrics_repository
134
-
135
- repos
133
+ {
134
+ splits: @splits_repository,
135
+ segments: @segments_repository,
136
+ impressions: @impressions_repository,
137
+ events: @events_repository,
138
+ metrics: @metrics_repository
139
+ }
136
140
  end
137
141
 
138
142
  def start_localhost_components
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'concurrent/atomics'
4
3
  require 'socketry'
5
4
  require 'uri'
6
5
 
@@ -9,15 +8,16 @@ module SplitIoClient
9
8
  module EventSource
10
9
  class Client
11
10
  DEFAULT_READ_TIMEOUT = 70
11
+ CONNECT_TIMEOUT = 30_000
12
12
  KEEP_ALIVE_RESPONSE = "c\r\n:keepalive\n\n\r\n".freeze
13
+ ERROR_EVENT_TYPE = 'error'.freeze
13
14
 
14
15
  def initialize(config, read_timeout: DEFAULT_READ_TIMEOUT)
15
16
  @config = config
16
17
  @read_timeout = read_timeout
17
18
  @connected = Concurrent::AtomicBoolean.new(false)
18
19
  @socket = nil
19
- @back_off = BackOff.new(@config.streaming_reconnect_back_off_base)
20
-
20
+ @event_parser = SSE::EventSource::EventParser.new(config)
21
21
  @on = { event: ->(_) {}, connected: ->(_) {}, disconnect: ->(_) {} }
22
22
 
23
23
  yield self if block_given?
@@ -35,8 +35,8 @@ module SplitIoClient
35
35
  @on[:disconnect] = action
36
36
  end
37
37
 
38
- def close
39
- dispatch_disconnect
38
+ def close(reconnect = false)
39
+ dispatch_disconnect(reconnect)
40
40
  @connected.make_false
41
41
  SplitIoClient::Helpers::ThreadHelper.stop(:connect_stream, @config)
42
42
  @socket&.close
@@ -46,10 +46,16 @@ module SplitIoClient
46
46
 
47
47
  def start(url)
48
48
  @uri = URI(url)
49
+ latch = Concurrent::CountDownLatch.new(1)
50
+
51
+ connect_thread(latch)
49
52
 
50
- connect_thread
53
+ return false unless latch.wait(CONNECT_TIMEOUT)
54
+
55
+ connected?
51
56
  rescue StandardError => e
52
57
  @config.logger.error("SSEClient start Error: #{e.inspect}")
58
+ connected?
53
59
  end
54
60
 
55
61
  def connected?
@@ -58,18 +64,15 @@ module SplitIoClient
58
64
 
59
65
  private
60
66
 
61
- def connect_thread
67
+ def connect_thread(latch)
62
68
  @config.threads[:connect_stream] = Thread.new do
63
69
  @config.logger.info('Starting connect_stream thread ...') if @config.debug_enabled
64
- connect_stream
70
+ connect_stream(latch)
65
71
  end
66
72
  end
67
73
 
68
- def connect_stream
69
- interval = @back_off.interval
70
- sleep(interval) if interval.positive?
71
-
72
- socket_write
74
+ def connect_stream(latch)
75
+ socket_write(latch)
73
76
 
74
77
  while @connected.value
75
78
  begin
@@ -77,24 +80,24 @@ module SplitIoClient
77
80
 
78
81
  raise 'eof exception' if partial_data == :eof
79
82
  rescue StandardError => e
80
- @config.logger.error(e.inspect) if @config.debug_enabled
81
- @connected.make_false
82
- @socket&.close
83
- @socket = nil
84
- connect_stream
83
+ @config.logger.error('Error reading partial data: ' + e.inspect) if @config.debug_enabled
84
+ close(true) # close conexion & reconnect
85
+ return
85
86
  end
86
87
 
87
88
  process_data(partial_data)
88
89
  end
89
90
  end
90
91
 
91
- def socket_write
92
+ def socket_write(latch)
92
93
  @socket = socket_connect
93
94
  @socket.write(build_request(@uri))
94
95
  dispatch_connected
95
96
  rescue StandardError => e
96
97
  @config.logger.error("Error during connecting to #{@uri.host}. Error: #{e.inspect}")
97
98
  close
99
+ ensure
100
+ latch.count_down
98
101
  end
99
102
 
100
103
  def socket_connect
@@ -104,11 +107,11 @@ module SplitIoClient
104
107
  end
105
108
 
106
109
  def process_data(partial_data)
107
- unless partial_data.nil? || partial_data == KEEP_ALIVE_RESPONSE
108
- @config.logger.debug("Event partial data: #{partial_data}") if @config.debug_enabled
109
- buffer = read_partial_data(partial_data)
110
- parse_event(buffer)
111
- end
110
+ return if partial_data.nil? || partial_data == KEEP_ALIVE_RESPONSE
111
+
112
+ @config.logger.debug("Event partial data: #{partial_data}") if @config.debug_enabled
113
+ events = @event_parser.parse(partial_data)
114
+ events.each { |event| process_event(event) }
112
115
  rescue StandardError => e
113
116
  @config.logger.error("process_data error: #{e.inspect}")
114
117
  end
@@ -122,64 +125,38 @@ module SplitIoClient
122
125
  req
123
126
  end
124
127
 
125
- def read_partial_data(data)
126
- buffer = ''
127
- buffer << data
128
- buffer.chomp!
129
- buffer.split("\n")
130
- end
131
-
132
- def parse_event(buffer)
133
- type = nil
134
-
135
- buffer.each do |d|
136
- splited_data = d.split(':')
137
-
138
- case splited_data[0]
139
- when 'event'
140
- type = splited_data[1].strip
141
- when 'data'
142
- data = parse_event_data(d, type)
143
- unless type.nil? || data[:data].nil?
144
- event = StreamData.new(type, data[:client_id], data[:data], data[:channel])
145
- dispatch_event(event)
146
- end
147
- end
128
+ def process_event(event)
129
+ case event.event_type
130
+ when ERROR_EVENT_TYPE
131
+ dispatch_error(event)
132
+ else
133
+ dispatch_event(event)
148
134
  end
149
- rescue StandardError => e
150
- @config.logger.error("Error during parsing a event: #{e.inspect}")
151
135
  end
152
136
 
153
- def parse_event_data(data, type)
154
- event_data = JSON.parse(data.sub('data: ', ''))
155
- client_id = event_data['clientId']&.strip
156
- channel = event_data['channel']&.strip
157
- parsed_data = JSON.parse(event_data['data']) unless type == 'error'
158
- parsed_data = event_data if type == 'error'
159
-
160
- { client_id: client_id, channel: channel, data: parsed_data }
137
+ def dispatch_error(event)
138
+ @config.logger.error("Event error: #{event.event_type}, #{event.data}")
139
+ if event.data['code'] >= 40_140 && event.data['code'] <= 40_149
140
+ close(true) # close conexion & reconnect
141
+ elsif event.data['code'] >= 40_000 && event.data['code'] <= 49_999
142
+ close # close conexion
143
+ end
161
144
  end
162
145
 
163
146
  def dispatch_event(event)
164
- raise SSEClientException.new(event), 'Error event' if event.event_type == 'error'
165
-
166
147
  @config.logger.debug("Dispatching event: #{event.event_type}, #{event.channel}") if @config.debug_enabled
167
148
  @on[:event].call(event)
168
- rescue SSEClientException => e
169
- @config.logger.error("Event error: #{e.event.event_type}, #{e.event.data}")
170
- close
171
149
  end
172
150
 
173
151
  def dispatch_connected
174
152
  @connected.make_true
175
- @back_off.reset
176
153
  @config.logger.debug('Dispatching connected') if @config.debug_enabled
177
154
  @on[:connected].call
178
155
  end
179
156
 
180
- def dispatch_disconnect
157
+ def dispatch_disconnect(reconnect)
181
158
  @config.logger.debug('Dispatching disconnect') if @config.debug_enabled
182
- @on[:disconnect].call
159
+ @on[:disconnect].call(reconnect)
183
160
  end
184
161
  end
185
162
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: false
2
+
3
+ module SplitIoClient
4
+ module SSE
5
+ module EventSource
6
+ class EventParser
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def parse(raw_event)
12
+ type = nil
13
+ events = []
14
+ buffer = read_partial_data(raw_event)
15
+
16
+ buffer.each do |d|
17
+ splited_data = d.split(':')
18
+
19
+ case splited_data[0]
20
+ when 'event'
21
+ type = splited_data[1].strip
22
+ when 'data'
23
+ data = parse_event_data(d, type)
24
+ events << StreamData.new(type, data[:client_id], data[:data], data[:channel]) unless type.nil? || data[:data].nil?
25
+ end
26
+ end
27
+
28
+ events
29
+ rescue StandardError => e
30
+ @config.logger.error("Error during parsing a event: #{e.inspect}")
31
+ []
32
+ end
33
+
34
+ private
35
+
36
+ def parse_event_data(data, type)
37
+ event_data = JSON.parse(data.sub('data: ', ''))
38
+ client_id = event_data['clientId']&.strip
39
+ channel = event_data['channel']&.strip
40
+ parsed_data = JSON.parse(event_data['data']) unless type == 'error'
41
+ parsed_data = event_data if type == 'error'
42
+
43
+ { client_id: client_id, channel: channel, data: parsed_data }
44
+ end
45
+
46
+ def read_partial_data(data)
47
+ buffer = ''
48
+ buffer << data
49
+ buffer.chomp!
50
+ buffer.split("\n")
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -14,7 +14,7 @@ module SplitIoClient
14
14
  @sse_client = SSE::EventSource::Client.new(@config) do |client|
15
15
  client.on_event { |event| handle_incoming_message(event) }
16
16
  client.on_connected { process_connected }
17
- client.on_disconnect { process_disconnect }
17
+ client.on_disconnect { |reconnect| process_disconnect(reconnect) }
18
18
  end
19
19
 
20
20
  @on = { connected: ->(_) {}, disconnect: ->(_) {} }
@@ -56,8 +56,8 @@ module SplitIoClient
56
56
  @on[:disconnect] = action
57
57
  end
58
58
 
59
- def process_disconnect
60
- @on[:disconnect].call
59
+ def process_disconnect(reconnect)
60
+ @on[:disconnect].call(reconnect)
61
61
  end
62
62
 
63
63
  private
@@ -8,27 +8,39 @@ module SplitIoClient
8
8
  @synchronizer = synchronizer
9
9
  @config = config
10
10
  @segments_repository = segments_repository
11
- @queue = nil
12
- end
13
-
14
- def start
15
- return if SplitIoClient::Helpers::ThreadHelper.alive?(:segment_update_worker, @config)
16
-
17
11
  @queue = Queue.new
18
- perform_thread
12
+ @running = Concurrent::AtomicBoolean.new(false)
19
13
  end
20
14
 
21
15
  def add_to_queue(change_number, segment_name)
22
- return if @queue.nil?
16
+ unless @running.value
17
+ @config.logger.debug('segments worker not running.')
18
+ return
19
+ end
23
20
 
24
21
  item = { change_number: change_number, segment_name: segment_name }
25
22
  @config.logger.debug("SegmentsWorker add to queue #{item}")
26
23
  @queue.push(item)
27
24
  end
28
25
 
26
+ def start
27
+ if @running.value
28
+ @config.logger.debug('segments worker already running.')
29
+ return
30
+ end
31
+
32
+ @running.make_true
33
+ perform_thread
34
+ end
35
+
29
36
  def stop
37
+ unless @running.value
38
+ @config.logger.debug('segments worker not running.')
39
+ return
40
+ end
41
+
42
+ @running.make_false
30
43
  SplitIoClient::Helpers::ThreadHelper.stop(:segment_update_worker, @config)
31
- @queue = nil
32
44
  end
33
45
 
34
46
  private
@@ -8,35 +8,53 @@ module SplitIoClient
8
8
  @synchronizer = synchronizer
9
9
  @config = config
10
10
  @splits_repository = splits_repository
11
+ @queue = Queue.new
12
+ @running = Concurrent::AtomicBoolean.new(false)
11
13
  end
12
14
 
13
15
  def start
14
- return if SplitIoClient::Helpers::ThreadHelper.alive?(:split_update_worker, @config)
16
+ if @running.value
17
+ @config.logger.debug('splits worker already running.')
18
+ return
19
+ end
15
20
 
16
- @queue = Queue.new
21
+ @running.make_true
17
22
  perform_thread
18
23
  end
19
24
 
25
+ def stop
26
+ unless @running.value
27
+ @config.logger.debug('splits worker not running.')
28
+ return
29
+ end
30
+
31
+ @running.make_false
32
+ SplitIoClient::Helpers::ThreadHelper.stop(:split_update_worker, @config)
33
+ end
34
+
20
35
  def add_to_queue(change_number)
21
- return if @queue.nil?
36
+ unless @running.value
37
+ @config.logger.debug('splits worker not running.')
38
+ return
39
+ end
22
40
 
23
41
  @config.logger.debug("SplitsWorker add to queue #{change_number}")
24
42
  @queue.push(change_number)
25
43
  end
26
44
 
27
45
  def kill_split(change_number, split_name, default_treatment)
28
- return if @queue.nil?
46
+ unless @running.value
47
+ @config.logger.debug('splits worker not running.')
48
+ return
49
+ end
50
+
51
+ return if @splits_repository.get_change_number.to_i > change_number
29
52
 
30
53
  @config.logger.debug("SplitsWorker kill #{split_name}, #{change_number}")
31
54
  @splits_repository.kill(change_number, split_name, default_treatment)
32
55
  add_to_queue(change_number)
33
56
  end
34
57
 
35
- def stop
36
- SplitIoClient::Helpers::ThreadHelper.stop(:split_update_worker, @config)
37
- @queue = nil
38
- end
39
-
40
58
  private
41
59
 
42
60
  def perform
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '7.1.4.pre.rc19'
2
+ VERSION = '7.2.2.pre.rc1'
3
3
  end
@@ -55,7 +55,7 @@ Gem::Specification.new do |spec|
55
55
  spec.add_runtime_dependency 'jwt', '>= 2.2.1'
56
56
  spec.add_runtime_dependency 'lru_redux'
57
57
  spec.add_runtime_dependency 'net-http-persistent', '>= 2.9'
58
- spec.add_runtime_dependency 'redis', '>= 3.2'
58
+ spec.add_runtime_dependency 'redis', '>= 4.2.2'
59
59
  spec.add_runtime_dependency 'socketry', '~> 0.5.1'
60
60
  spec.add_runtime_dependency 'thread_safe', '>= 0.3'
61
61
  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.1.4.pre.rc19
4
+ version: 7.2.2.pre.rc1
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-09-23 00:00:00.000000000 Z
11
+ date: 2020-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allocation_stats
@@ -268,14 +268,14 @@ dependencies:
268
268
  requirements:
269
269
  - - ">="
270
270
  - !ruby/object:Gem::Version
271
- version: '3.2'
271
+ version: 4.2.2
272
272
  type: :runtime
273
273
  prerelease: false
274
274
  version_requirements: !ruby/object:Gem::Requirement
275
275
  requirements:
276
276
  - - ">="
277
277
  - !ruby/object:Gem::Version
278
- version: '3.2'
278
+ version: 4.2.2
279
279
  - !ruby/object:Gem::Dependency
280
280
  name: socketry
281
281
  requirement: !ruby/object:Gem::Requirement
@@ -425,6 +425,7 @@ files:
425
425
  - lib/splitclient-rb/split_logger.rb
426
426
  - lib/splitclient-rb/sse/event_source/back_off.rb
427
427
  - lib/splitclient-rb/sse/event_source/client.rb
428
+ - lib/splitclient-rb/sse/event_source/event_parser.rb
428
429
  - lib/splitclient-rb/sse/event_source/event_types.rb
429
430
  - lib/splitclient-rb/sse/event_source/stream_data.rb
430
431
  - lib/splitclient-rb/sse/notification_manager_keeper.rb