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
@@ -8,7 +8,7 @@ module SplitIoClient
|
|
8
8
|
module SSE
|
9
9
|
module EventSource
|
10
10
|
class Client
|
11
|
-
DEFAULT_READ_TIMEOUT =
|
11
|
+
DEFAULT_READ_TIMEOUT = 70
|
12
12
|
KEEP_ALIVE_RESPONSE = "c\r\n:keepalive\n\n\r\n".freeze
|
13
13
|
|
14
14
|
def initialize(url, config, read_timeout: DEFAULT_READ_TIMEOUT)
|
@@ -17,13 +17,13 @@ module SplitIoClient
|
|
17
17
|
@read_timeout = read_timeout
|
18
18
|
@connected = Concurrent::AtomicBoolean.new(false)
|
19
19
|
@socket = nil
|
20
|
+
@back_off = BackOff.new(@config.streaming_reconnect_back_off_base)
|
20
21
|
|
21
|
-
@on = { event: ->(_) {},
|
22
|
+
@on = { event: ->(_) {}, connected: ->(_) {}, disconnect: ->(_) {} }
|
22
23
|
|
23
24
|
yield self if block_given?
|
24
25
|
|
25
26
|
connect_thread
|
26
|
-
|
27
27
|
connect_passenger_forked if defined?(PhusionPassenger)
|
28
28
|
end
|
29
29
|
|
@@ -31,28 +31,29 @@ module SplitIoClient
|
|
31
31
|
@on[:event] = action
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
@on[:
|
34
|
+
def on_connected(&action)
|
35
|
+
@on[:connected] = action
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_disconnect(&action)
|
39
|
+
@on[:disconnect] = action
|
36
40
|
end
|
37
41
|
|
38
42
|
def close
|
43
|
+
dispatch_disconnect
|
39
44
|
@connected.make_false
|
40
45
|
@socket&.close
|
41
46
|
@socket = nil
|
42
47
|
end
|
43
48
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
Status::DISCONNECTED
|
49
|
+
def connected?
|
50
|
+
@connected.value
|
48
51
|
end
|
49
52
|
|
50
53
|
private
|
51
54
|
|
52
55
|
def connect_thread
|
53
|
-
@config.threads[:connect_stream] = Thread.new
|
54
|
-
connect_stream
|
55
|
-
end
|
56
|
+
@config.threads[:connect_stream] = Thread.new { connect_stream }
|
56
57
|
end
|
57
58
|
|
58
59
|
def connect_passenger_forked
|
@@ -60,54 +61,58 @@ module SplitIoClient
|
|
60
61
|
end
|
61
62
|
|
62
63
|
def connect_stream
|
63
|
-
|
64
|
+
interval = @back_off.interval
|
65
|
+
sleep(interval) if interval.positive?
|
64
66
|
|
65
|
-
|
66
|
-
@socket = socket_connect
|
67
|
+
@config.logger.info("Connecting to #{@uri.host}...")
|
67
68
|
|
68
|
-
|
69
|
-
@connected.make_true
|
70
|
-
rescue StandardError => e
|
71
|
-
dispatch_error(e.inspect)
|
72
|
-
end
|
69
|
+
socket_write
|
73
70
|
|
74
71
|
while @connected.value
|
75
72
|
begin
|
76
73
|
partial_data = @socket.readpartial(2048, timeout: @read_timeout)
|
77
74
|
rescue Socketry::TimeoutError
|
78
|
-
@config.logger.error("Socket read time out in #{@read_timeout}")
|
79
|
-
|
75
|
+
@config.logger.error("Socket read time out in #{@read_timeout} seconds")
|
76
|
+
close
|
80
77
|
connect_stream
|
81
78
|
end
|
82
79
|
|
83
|
-
|
80
|
+
process_data(partial_data)
|
84
81
|
end
|
85
82
|
end
|
86
83
|
|
84
|
+
def socket_write
|
85
|
+
@socket = socket_connect
|
86
|
+
@socket.write(build_request(@uri))
|
87
|
+
dispatch_connected
|
88
|
+
rescue StandardError => e
|
89
|
+
@config.logger.error("Error during connecting to #{@uri.host}. Error: #{e.inspect}")
|
90
|
+
close
|
91
|
+
end
|
92
|
+
|
87
93
|
def socket_connect
|
88
94
|
return Socketry::SSL::Socket.connect(@uri.host, @uri.port) if @uri.scheme.casecmp('https').zero?
|
89
95
|
|
90
96
|
Socketry::TCP::Socket.connect(@uri.host, @uri.port)
|
91
97
|
end
|
92
98
|
|
93
|
-
def
|
94
|
-
unless partial_data.nil?
|
99
|
+
def process_data(partial_data)
|
100
|
+
unless partial_data.nil? || partial_data == KEEP_ALIVE_RESPONSE
|
95
101
|
@config.logger.debug("Event partial data: #{partial_data}")
|
96
102
|
buffer = read_partial_data(partial_data)
|
97
|
-
|
103
|
+
events = parse_event(buffer)
|
98
104
|
|
99
|
-
dispatch_event(
|
105
|
+
dispatch_event(events)
|
100
106
|
end
|
101
107
|
rescue StandardError => e
|
102
|
-
|
108
|
+
@config.logger.error("Error during processing data: #{e.inspect}")
|
103
109
|
end
|
104
110
|
|
105
111
|
def build_request(uri)
|
106
112
|
req = "GET #{uri.request_uri} HTTP/1.1\r\n"
|
107
113
|
req << "Host: #{uri.host}\r\n"
|
108
114
|
req << "Accept: text/event-stream\r\n"
|
109
|
-
req << "Cache-Control: no-cache\r\n"
|
110
|
-
req << "\r\n"
|
115
|
+
req << "Cache-Control: no-cache\r\n\r\n"
|
111
116
|
@config.logger.debug("Request info: #{req}")
|
112
117
|
req
|
113
118
|
end
|
@@ -120,43 +125,61 @@ module SplitIoClient
|
|
120
125
|
end
|
121
126
|
|
122
127
|
def parse_event(buffer)
|
123
|
-
|
124
|
-
|
125
|
-
client_id = nil
|
128
|
+
type = nil
|
129
|
+
events = []
|
126
130
|
|
127
131
|
buffer.each do |d|
|
128
132
|
splited_data = d.split(':')
|
129
133
|
|
130
134
|
case splited_data[0]
|
131
135
|
when 'event'
|
132
|
-
|
136
|
+
type = splited_data[1].strip
|
133
137
|
when 'data'
|
134
|
-
|
135
|
-
client_id
|
136
|
-
parsed_data = JSON.parse(event_data['data'])
|
138
|
+
data = parse_event_data(d, type)
|
139
|
+
events << StreamData.new(type, data[:client_id], data[:data], data[:channel]) unless type.nil? || data[:data].nil?
|
137
140
|
end
|
138
141
|
end
|
139
142
|
|
140
|
-
|
141
|
-
|
142
|
-
raise 'Invalid event format.'
|
143
|
+
events
|
143
144
|
rescue StandardError => e
|
144
|
-
|
145
|
-
|
145
|
+
@config.logger.error("Error during parsing a event: #{e.inspect}")
|
146
|
+
[]
|
147
|
+
end
|
148
|
+
|
149
|
+
def parse_event_data(data, type)
|
150
|
+
event_data = JSON.parse(data.sub('data: ', ''))
|
151
|
+
client_id = event_data['clientId']&.strip
|
152
|
+
channel = event_data['channel']&.strip
|
153
|
+
parsed_data = JSON.parse(event_data['data']) unless type == 'error'
|
154
|
+
parsed_data = event_data if type == 'error'
|
155
|
+
|
156
|
+
{ client_id: client_id, channel: channel, data: parsed_data }
|
146
157
|
end
|
147
158
|
|
148
|
-
def dispatch_event(
|
149
|
-
|
150
|
-
|
159
|
+
def dispatch_event(events)
|
160
|
+
events.each do |event|
|
161
|
+
raise SSEClientException.new(event), 'Error event' if event.event_type == 'error'
|
162
|
+
|
163
|
+
@config.logger.debug("Dispatching event: #{event.event_type}, #{event.channel}")
|
164
|
+
@on[:event].call(event)
|
165
|
+
end
|
166
|
+
rescue SSEClientException => e
|
167
|
+
@config.logger.error("Event error: #{e.event.event_type}, #{e.event.data}")
|
168
|
+
close
|
151
169
|
end
|
152
170
|
|
153
|
-
def
|
154
|
-
@
|
155
|
-
@
|
171
|
+
def dispatch_connected
|
172
|
+
@connected.make_true
|
173
|
+
@back_off.reset
|
174
|
+
@config.logger.debug('Dispatching connected')
|
175
|
+
@on[:connected].call
|
156
176
|
end
|
157
|
-
end
|
158
177
|
|
159
|
-
|
178
|
+
def dispatch_disconnect
|
179
|
+
@config.logger.debug('Dispatching disconnect')
|
180
|
+
@on[:disconnect].call
|
181
|
+
end
|
182
|
+
end
|
160
183
|
end
|
161
184
|
end
|
162
185
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module SSE
|
5
|
+
module EventSource
|
6
|
+
class StreamData
|
7
|
+
attr_reader :event_type, :channel, :data, :client_id
|
8
|
+
|
9
|
+
def initialize(event_type, client_id, data, channel)
|
10
|
+
@event_type = event_type
|
11
|
+
@client_id = client_id
|
12
|
+
@data = data
|
13
|
+
@channel = channel&.gsub(SplitIoClient::Constants::OCCUPANCY_CHANNEL_PREFIX, '')
|
14
|
+
end
|
15
|
+
|
16
|
+
def occupancy?
|
17
|
+
@channel.include? 'control'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'concurrent/atomics'
|
4
|
+
|
5
|
+
module SplitIoClient
|
6
|
+
module SSE
|
7
|
+
class NotificationManagerKeeper
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
@polling_on = Concurrent::AtomicBoolean.new(false)
|
11
|
+
@on = { occupancy: ->(_) {} }
|
12
|
+
|
13
|
+
yield self if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_incoming_occupancy_event(event)
|
17
|
+
process_event(event.data['metrics']['publishers']) if event.channel == SplitIoClient::Constants::CONTROL_PRI
|
18
|
+
rescue StandardError => e
|
19
|
+
@config.logger.error(e)
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_occupancy(&action)
|
23
|
+
@on[:occupancy] = action
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def process_event(publishers)
|
29
|
+
@config.logger.debug("Occupancy process event with #{publishers} publishers and polling on: #{@polling_on.value}")
|
30
|
+
if publishers <= 0 && !@polling_on.value
|
31
|
+
@polling_on.make_true
|
32
|
+
dispatch_occupancy_event(false)
|
33
|
+
elsif publishers >= 1 && @polling_on.value
|
34
|
+
@polling_on.make_false
|
35
|
+
dispatch_occupancy_event(true)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def dispatch_occupancy_event(publisher_available)
|
40
|
+
@config.logger.debug("Dispatching occupancy event with publisher avaliable: #{publisher_available}")
|
41
|
+
@on[:occupancy].call(publisher_available)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module SSE
|
5
|
+
class NotificationProcessor
|
6
|
+
def initialize(config, splits_worker, segments_worker)
|
7
|
+
@config = config
|
8
|
+
@splits_worker = splits_worker
|
9
|
+
@segments_worker = segments_worker
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(incoming_notification)
|
13
|
+
case incoming_notification.data['type']
|
14
|
+
when SSE::EventSource::EventTypes::SPLIT_UPDATE
|
15
|
+
process_split_update(incoming_notification)
|
16
|
+
when SSE::EventSource::EventTypes::SPLIT_KILL
|
17
|
+
process_split_kill(incoming_notification)
|
18
|
+
when SSE::EventSource::EventTypes::SEGMENT_UPDATE
|
19
|
+
process_segment_update(incoming_notification)
|
20
|
+
else
|
21
|
+
@config.logger.error("Incorrect event type: #{incoming_notification}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def process_split_update(notification)
|
28
|
+
@config.logger.debug("SPLIT UPDATE notification received: #{notification}")
|
29
|
+
@splits_worker.add_to_queue(notification.data['changeNumber'])
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_split_kill(notification)
|
33
|
+
@config.logger.debug("SPLIT KILL notification received: #{notification}")
|
34
|
+
change_number = notification.data['changeNumber']
|
35
|
+
default_treatment = notification.data['defaultTreatment']
|
36
|
+
split_name = notification.data['splitName']
|
37
|
+
|
38
|
+
@splits_worker.kill_split(change_number, split_name, default_treatment)
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_segment_update(notification)
|
42
|
+
@config.logger.debug("SEGMENT UPDATE notification received: #{notification}")
|
43
|
+
change_number = notification.data['changeNumber']
|
44
|
+
segment_name = notification.data['segmentName']
|
45
|
+
|
46
|
+
@segments_worker.add_to_queue(change_number, segment_name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -5,78 +5,74 @@ module SplitIoClient
|
|
5
5
|
class SSEHandler
|
6
6
|
attr_reader :sse_client
|
7
7
|
|
8
|
-
def initialize(config,
|
8
|
+
def initialize(config, synchronizer, splits_repository, segments_repository, notification_manager_keeper)
|
9
9
|
@config = config
|
10
|
-
@
|
11
|
-
@splits_worker =
|
12
|
-
@segments_worker =
|
13
|
-
@control_worker =
|
10
|
+
@notification_manager_keeper = notification_manager_keeper
|
11
|
+
@splits_worker = SplitIoClient::SSE::Workers::SplitsWorker.new(synchronizer, config, splits_repository)
|
12
|
+
@segments_worker = SplitIoClient::SSE::Workers::SegmentsWorker.new(synchronizer, config, segments_repository)
|
13
|
+
@control_worker = SplitIoClient::SSE::Workers::ControlWorker.new(config)
|
14
|
+
@notification_processor = SplitIoClient::SSE::NotificationProcessor.new(config, @splits_worker, @segments_worker)
|
14
15
|
|
15
|
-
@
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
16
|
+
@on = { connected: ->(_) {}, disconnect: ->(_) {} }
|
19
17
|
|
20
|
-
|
21
|
-
|
18
|
+
yield self if block_given?
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
process_event(event)
|
26
|
-
end
|
21
|
+
def start(token_jwt, channels)
|
22
|
+
url = "#{@config.streaming_service_url}?channels=#{channels}&v=1.1&accessToken=#{token_jwt}"
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
@sse_client = SSE::EventSource::Client.new(url, @config) do |client|
|
25
|
+
client.on_event { |event| handle_incoming_message(event) }
|
26
|
+
client.on_connected { process_connected }
|
27
|
+
client.on_disconnect { process_disconnect }
|
31
28
|
end
|
29
|
+
end
|
32
30
|
|
33
|
-
|
31
|
+
def stop
|
32
|
+
@sse_client&.close
|
33
|
+
@sse_client = nil
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
|
38
|
-
when SSE::EventSource::EventTypes::SPLIT_UPDATE
|
39
|
-
split_update_notification(event)
|
40
|
-
when SSE::EventSource::EventTypes::SPLIT_KILL
|
41
|
-
split_kill_notification(event)
|
42
|
-
when SSE::EventSource::EventTypes::SEGMENT_UPDATE
|
43
|
-
segment_update_notification(event)
|
44
|
-
when SSE::EventSource::EventTypes::CONTROL
|
45
|
-
control_notification(event)
|
46
|
-
else
|
47
|
-
@config.logger.error("Incorrect event type: #{event}")
|
48
|
-
end
|
36
|
+
def connected?
|
37
|
+
@sse_client&.connected? || false
|
49
38
|
end
|
50
39
|
|
51
|
-
def
|
52
|
-
@
|
40
|
+
def start_workers
|
41
|
+
@splits_worker.start
|
42
|
+
@segments_worker.start
|
43
|
+
@control_worker.start
|
53
44
|
end
|
54
45
|
|
55
|
-
def
|
56
|
-
@
|
57
|
-
@
|
46
|
+
def stop_workers
|
47
|
+
@splits_worker.stop
|
48
|
+
@segments_worker.stop
|
49
|
+
@control_worker.stop
|
58
50
|
end
|
59
51
|
|
60
|
-
def
|
61
|
-
@
|
52
|
+
def on_connected(&action)
|
53
|
+
@on[:connected] = action
|
54
|
+
end
|
62
55
|
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
def on_disconnect(&action)
|
57
|
+
@on[:disconnect] = action
|
58
|
+
end
|
66
59
|
|
67
|
-
|
60
|
+
def process_disconnect
|
61
|
+
@on[:disconnect].call
|
68
62
|
end
|
69
63
|
|
70
|
-
|
71
|
-
@config.logger.debug("SEGMENT UPDATE notification received: #{event}")
|
72
|
-
change_number = event.data['changeNumber']
|
73
|
-
segment_name = event.data['segmentName']
|
64
|
+
private
|
74
65
|
|
75
|
-
|
66
|
+
def process_connected
|
67
|
+
@on[:connected].call
|
76
68
|
end
|
77
69
|
|
78
|
-
def
|
79
|
-
|
70
|
+
def handle_incoming_message(notification)
|
71
|
+
if notification.occupancy?
|
72
|
+
@notification_manager_keeper.handle_incoming_occupancy_event(notification)
|
73
|
+
else
|
74
|
+
@notification_processor.process(notification)
|
75
|
+
end
|
80
76
|
end
|
81
77
|
end
|
82
78
|
end
|
@@ -4,23 +4,28 @@ module SplitIoClient
|
|
4
4
|
module SSE
|
5
5
|
module Workers
|
6
6
|
class ControlWorker
|
7
|
-
def initialize(
|
8
|
-
@adapter = adapter
|
7
|
+
def initialize(config)
|
9
8
|
@config = config
|
9
|
+
end
|
10
10
|
|
11
|
+
def start
|
11
12
|
perform_thread
|
12
|
-
|
13
13
|
perform_passenger_forked if defined?(PhusionPassenger)
|
14
14
|
end
|
15
15
|
|
16
|
+
def stop
|
17
|
+
SplitIoClient::Helpers::ThreadHelper.stop(:control_worker, @config)
|
18
|
+
end
|
19
|
+
|
16
20
|
private
|
17
21
|
|
18
22
|
def perform
|
19
|
-
# TODO: IMPLEMENT THIS METHOD
|
23
|
+
# TODO: IMPLEMENT THIS METHOD.
|
20
24
|
end
|
21
25
|
|
22
26
|
def perform_thread
|
23
|
-
@config.threads[:
|
27
|
+
@config.threads[:control_worker] = Thread.new do
|
28
|
+
@config.logger.debug('Starting control worker ...')
|
24
29
|
perform
|
25
30
|
end
|
26
31
|
end
|
@@ -4,22 +4,28 @@ module SplitIoClient
|
|
4
4
|
module SSE
|
5
5
|
module Workers
|
6
6
|
class SegmentsWorker
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(synchronizer, config, segments_repository)
|
8
|
+
@synchronizer = synchronizer
|
9
9
|
@config = config
|
10
10
|
@segments_repository = segments_repository
|
11
11
|
@queue = Queue.new
|
12
|
+
end
|
12
13
|
|
14
|
+
def start
|
13
15
|
perform_thread
|
14
|
-
|
15
16
|
perform_passenger_forked if defined?(PhusionPassenger)
|
16
17
|
end
|
17
18
|
|
18
19
|
def add_to_queue(change_number, segment_name)
|
19
20
|
item = { change_number: change_number, segment_name: segment_name }
|
21
|
+
@config.logger.debug("SegmentsWorker add to queue #{item}")
|
20
22
|
@queue.push(item)
|
21
23
|
end
|
22
24
|
|
25
|
+
def stop
|
26
|
+
SplitIoClient::Helpers::ThreadHelper.stop(:segment_update_worker, @config)
|
27
|
+
end
|
28
|
+
|
23
29
|
private
|
24
30
|
|
25
31
|
def perform
|
@@ -28,12 +34,16 @@ module SplitIoClient
|
|
28
34
|
change_number = item[:change_number]
|
29
35
|
since = @segments_repository.get_change_number(segment_name)
|
30
36
|
|
31
|
-
|
37
|
+
unless since >= change_number
|
38
|
+
@config.logger.debug("SegmentsWorker fetch_segment with #{since}")
|
39
|
+
@synchronizer.fetch_segment(segment_name)
|
40
|
+
end
|
32
41
|
end
|
33
42
|
end
|
34
43
|
|
35
44
|
def perform_thread
|
36
45
|
@config.threads[:segment_update_worker] = Thread.new do
|
46
|
+
@config.logger.debug('Starting segments worker ...')
|
37
47
|
perform
|
38
48
|
end
|
39
49
|
end
|
@@ -4,37 +4,49 @@ module SplitIoClient
|
|
4
4
|
module SSE
|
5
5
|
module Workers
|
6
6
|
class SplitsWorker
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(synchronizer, config, splits_repository)
|
8
|
+
@synchronizer = synchronizer
|
9
9
|
@config = config
|
10
10
|
@splits_repository = splits_repository
|
11
11
|
@queue = Queue.new
|
12
|
+
end
|
12
13
|
|
14
|
+
def start
|
13
15
|
perform_thread
|
14
|
-
|
15
16
|
perform_passenger_forked if defined?(PhusionPassenger)
|
16
17
|
end
|
17
18
|
|
18
19
|
def add_to_queue(change_number)
|
20
|
+
@config.logger.debug("SplitsWorker add to queue #{change_number}")
|
19
21
|
@queue.push(change_number)
|
20
22
|
end
|
21
23
|
|
22
24
|
def kill_split(change_number, split_name, default_treatment)
|
25
|
+
@config.logger.debug("SplitsWorker kill #{split_name}, #{change_number}")
|
23
26
|
@splits_repository.kill(change_number, split_name, default_treatment)
|
24
27
|
add_to_queue(change_number)
|
25
28
|
end
|
26
29
|
|
30
|
+
def stop
|
31
|
+
SplitIoClient::Helpers::ThreadHelper.stop(:split_update_worker, @config)
|
32
|
+
end
|
33
|
+
|
27
34
|
private
|
28
35
|
|
29
36
|
def perform
|
30
37
|
while (change_number = @queue.pop)
|
31
38
|
since = @splits_repository.get_change_number
|
32
|
-
|
39
|
+
|
40
|
+
unless since.to_i >= change_number
|
41
|
+
@config.logger.debug("SplitsWorker fetch_splits with #{since}")
|
42
|
+
@synchronizer.fetch_splits
|
43
|
+
end
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
36
47
|
def perform_thread
|
37
48
|
@config.threads[:split_update_worker] = Thread.new do
|
49
|
+
@config.logger.debug('Starting splits worker ...')
|
38
50
|
perform
|
39
51
|
end
|
40
52
|
end
|
data/lib/splitclient-rb.rb
CHANGED
@@ -2,6 +2,7 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
require 'splitclient-rb/version'
|
4
4
|
|
5
|
+
require 'splitclient-rb/constants'
|
5
6
|
require 'splitclient-rb/exceptions'
|
6
7
|
require 'splitclient-rb/cache/routers/impression_router'
|
7
8
|
require 'splitclient-rb/cache/adapters/memory_adapters/map_adapter'
|
@@ -35,6 +36,7 @@ require 'splitclient-rb/cache/stores/localhost_split_store'
|
|
35
36
|
|
36
37
|
require 'splitclient-rb/clients/split_client'
|
37
38
|
require 'splitclient-rb/managers/split_manager'
|
39
|
+
require 'splitclient-rb/helpers/thread_helper'
|
38
40
|
require 'splitclient-rb/split_factory'
|
39
41
|
require 'splitclient-rb/split_factory_builder'
|
40
42
|
require 'splitclient-rb/split_config'
|
@@ -52,7 +54,6 @@ require 'splitclient-rb/engine/api/splits'
|
|
52
54
|
require 'splitclient-rb/engine/api/events'
|
53
55
|
require 'splitclient-rb/engine/parser/condition'
|
54
56
|
require 'splitclient-rb/engine/parser/partition'
|
55
|
-
require 'splitclient-rb/engine/parser/split_adapter'
|
56
57
|
require 'splitclient-rb/engine/parser/evaluator'
|
57
58
|
require 'splitclient-rb/engine/matchers/matcher'
|
58
59
|
require 'splitclient-rb/engine/matchers/combiners'
|
@@ -83,18 +84,25 @@ require 'splitclient-rb/engine/metrics/binary_search_latency_tracker'
|
|
83
84
|
require 'splitclient-rb/engine/models/split'
|
84
85
|
require 'splitclient-rb/engine/models/label'
|
85
86
|
require 'splitclient-rb/engine/models/treatment'
|
87
|
+
require 'splitclient-rb/engine/auth_api_client'
|
88
|
+
require 'splitclient-rb/engine/push_manager'
|
89
|
+
require 'splitclient-rb/engine/sync_manager'
|
90
|
+
require 'splitclient-rb/engine/synchronizer'
|
86
91
|
require 'splitclient-rb/utilitites'
|
87
92
|
|
88
93
|
# redis metrics fixer
|
89
94
|
require 'splitclient-rb/redis_metrics_fixer'
|
90
95
|
|
91
96
|
# SSE
|
97
|
+
require 'splitclient-rb/sse/event_source/back_off'
|
92
98
|
require 'splitclient-rb/sse/event_source/client'
|
93
99
|
require 'splitclient-rb/sse/event_source/event_types'
|
94
|
-
require 'splitclient-rb/sse/event_source/
|
100
|
+
require 'splitclient-rb/sse/event_source/stream_data'
|
95
101
|
require 'splitclient-rb/sse/workers/control_worker'
|
96
102
|
require 'splitclient-rb/sse/workers/segments_worker'
|
97
103
|
require 'splitclient-rb/sse/workers/splits_worker'
|
104
|
+
require 'splitclient-rb/sse/notification_manager_keeper'
|
105
|
+
require 'splitclient-rb/sse/notification_processor'
|
98
106
|
require 'splitclient-rb/sse/sse_handler'
|
99
107
|
|
100
108
|
# C extension
|
data/splitclient-rb.gemspec
CHANGED
@@ -51,6 +51,7 @@ Gem::Specification.new do |spec|
|
|
51
51
|
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
52
52
|
spec.add_runtime_dependency 'faraday', '>= 0.8'
|
53
53
|
spec.add_runtime_dependency 'json', '>= 1.8'
|
54
|
+
spec.add_runtime_dependency 'jwt', '>= 2.2.1'
|
54
55
|
spec.add_runtime_dependency 'lru_redux'
|
55
56
|
spec.add_runtime_dependency 'net-http-persistent', '>= 2.9'
|
56
57
|
spec.add_runtime_dependency 'redis', '>= 3.2'
|