Skip to content

Commit 584e247

Browse files
authored
Merge pull request #599 from splitio/FME-10903-uograde-sdk
added tests
2 parents 8a68e43 + a746601 commit 584e247

2 files changed

Lines changed: 83 additions & 28 deletions

File tree

lib/splitclient-rb/sse/event_source/client.rb

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def initialize(config,
3838

3939
def close(status = nil)
4040
unless connected?
41-
log_if_debug('SSEClient already disconected.', 3)
41+
@config.logger.debug('SSEClient already disconected.')
4242
return
4343
end
4444

@@ -76,10 +76,10 @@ def connected?
7676

7777
def connect_thread(latch)
7878
@config.threads[:connect_stream] = Thread.new do
79-
log_if_debug('Starting connect_stream thread ...', 2)
79+
@config.logger.info('Starting connect_stream thread ...')
8080
new_status = connect_stream(latch)
8181
push_status(new_status)
82-
log_if_debug('connect_stream thread finished.', 2)
82+
@config.logger.info('connect_stream thread finished.')
8383
end
8484
end
8585

@@ -93,37 +93,38 @@ def connect_stream(latch)
9393

9494
raise 'eof exception' if partial_data == :eof
9595
rescue IO::WaitReadable => e
96-
log_if_debug("SSE client transient error: #{e.inspect}", 1)
96+
@config.logger.debug("SSE client transient error: #{e.inspect}")
9797
IO.select([@socket], nil, nil, @read_timeout)
9898
retry
9999
rescue Errno::ETIMEDOUT => e
100-
log_if_debug("SSE read operation timed out!: #{e.inspect}", 3)
100+
@config.logger.error("SSE read operation timed out!: #{e.inspect}")
101101
return Constants::PUSH_RETRYABLE_ERROR
102102
rescue EOFError => e
103-
log_if_debug("SSE read operation EOF Exception!: #{e.inspect}", 3)
103+
@config.logger.error("SSE read operation EOF Exception!: #{e.inspect}")
104104
raise 'eof exception'
105105
rescue Errno::EAGAIN => e
106-
log_if_debug("SSE client transient error: #{e.inspect}", 1)
106+
puts "transient error"
107+
@config.logger.debug("SSE client transient error: #{e.inspect}")
107108
IO.select([@socket], nil, nil, @read_timeout)
108109
retry
109110
rescue Errno::EBADF, IOError => e
110-
log_if_debug("SSE read operation EBADF or IOError: #{e.inspect}", 3)
111+
@config.logger.error("SSE read operation EBADF or IOError: #{e.inspect}")
111112
return nil
112113
rescue StandardError => e
113-
log_if_debug("SSE read operation StandardError: #{e.inspect}", 3)
114+
@config.logger.error("SSE read operation StandardError: #{e.inspect}")
114115
return nil if ENV['SPLITCLIENT_ENV'] == 'test'
115116

116-
log_if_debug("Error reading partial data: #{e.inspect}", 3)
117+
@config.logger.error("Error reading partial data: #{e.inspect}")
117118
return Constants::PUSH_RETRYABLE_ERROR
118119
end
119120
else
120-
@config.logger.debug("SSE read operation timed out, no data available.")
121+
@config.logger.error("SSE read operation timed out, no data available.")
121122
return Constants::PUSH_RETRYABLE_ERROR
122123
end
123124

124125
process_data(partial_data)
125126
end
126-
log_if_debug("SSE read operation exited: #{connected?}", 1)
127+
@config.logger.info("SSE read operation exited: #{connected?}")
127128

128129
nil
129130
end
@@ -134,7 +135,7 @@ def socket_write(latch)
134135
@socket.puts(build_request(@uri))
135136
true
136137
rescue StandardError => e
137-
log_if_debug("Error during connecting to #{@uri.host}. Error: #{e.inspect}", 3)
138+
@config.logger.error("Error during connecting to #{@uri.host}. Error: #{e.inspect}")
138139
latch.count_down
139140
false
140141
end
@@ -189,7 +190,7 @@ def socket_connect
189190
end
190191

191192
def process_data(partial_data)
192-
log_if_debug("Event partial data: #{partial_data}", 1)
193+
@config.logger.debug("Event partial data: #{partial_data}")
193194
return if partial_data.nil? || partial_data == KEEP_ALIVE_RESPONSE
194195

195196
events = @event_parser.parse(partial_data)
@@ -207,7 +208,7 @@ def build_request(uri)
207208
req << "SplitSDKMachineName: #{@config.machine_name}\r\n"
208209
req << "SplitSDKClientKey: #{@api_key.split(//).last(4).join}\r\n" unless @api_key.nil?
209210
req << "Cache-Control: no-cache\r\n\r\n"
210-
log_if_debug("Request info: #{req}", 1)
211+
@config.logger.debug("Request info: #{req}")
211212
req
212213
end
213214

@@ -245,19 +246,6 @@ def push_status(status)
245246
@config.logger.debug("Pushing new sse status: #{status}")
246247
@status_queue.push(status)
247248
end
248-
249-
def log_if_debug(text, level)
250-
if @config.debug_enabled
251-
case level
252-
when 1
253-
@config.logger.debug(text)
254-
when 2
255-
@config.logger.info(text)
256-
else
257-
@config.logger.error(text)
258-
end
259-
end
260-
end
261249
end
262250
end
263251
end

spec/sse/event_source/client_spec.rb

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'spec_helper'
44
require 'http_server_mock'
5+
require 'rspec/mocks'
56

67
describe SplitIoClient::SSE::EventSource::Client do
78
subject { SplitIoClient::SSE::EventSource::Client }
@@ -266,6 +267,72 @@
266267
stop_workers
267268
end
268269
end
270+
271+
it 'test exceptions' do
272+
mock_server do |server|
273+
server.setup_response('/') do |_, res|
274+
send_stream_content(res, event_split_update)
275+
end
276+
start_workers
277+
278+
sse_client = subject.new(config, api_token, telemetry_runtime_producer, event_parser, notification_manager_keeper, notification_processor, push_status_queue)
279+
280+
sse_client.instance_variable_set(:@uri, URI(server.base_uri))
281+
latch = Concurrent::CountDownLatch.new(1)
282+
283+
allow(sse_client).to receive(:read_first_event).and_raise(Errno::ETIMEDOUT)
284+
sse_client.send(:connect_stream, latch)
285+
expect(log.string).to include 'SSE read operation timed out!'
286+
287+
allow(sse_client).to receive(:read_first_event).and_raise(EOFError)
288+
expect { sse_client.send(:connect_stream, latch) }.to raise_error(RuntimeError)
289+
expect(log.string).to include 'SSE read operation EOF Exception!'
290+
291+
allow(sse_client).to receive(:read_first_event).and_raise(Errno::EBADF)
292+
sse_client.send(:connect_stream, latch)
293+
expect(log.string).to include 'SSE read operation EBADF or IOError'
294+
295+
allow(sse_client).to receive(:read_first_event).and_raise(IOError)
296+
sse_client.send(:connect_stream, latch)
297+
expect(log.string).to include 'SSE read operation EBADF or IOError'
298+
299+
allow(sse_client).to receive(:read_first_event).and_raise(StandardError)
300+
sse_client.send(:connect_stream, latch)
301+
expect(log.string).to include 'SSE read operation StandardError:'
302+
303+
stop_workers
304+
end
305+
end
306+
307+
it 'test retry with EAGAIN and IO::WaitReadable exceptions' do
308+
mock_server do |server|
309+
server.setup_response('/') do |_, res|
310+
send_stream_content(res, event_split_update)
311+
end
312+
start_workers
313+
314+
sse_client = subject.new(config, api_token, telemetry_runtime_producer, event_parser, notification_manager_keeper, notification_processor, push_status_queue)
315+
316+
sse_client.instance_variable_set(:@uri, URI(server.base_uri))
317+
latch = Concurrent::CountDownLatch.new(1)
318+
319+
allow(sse_client).to receive(:read_first_event).and_raise(Errno::EAGAIN)
320+
thr1 = Thread.new do
321+
sse_client.send(:connect_stream, latch)
322+
end
323+
allow(sse_client).to receive(:read_first_event).and_return(true)
324+
expect(thr1.status).to eq('run')
325+
326+
allow(sse_client).to receive(:read_first_event).and_raise(IO::WaitReadable)
327+
thr2 = Thread.new do
328+
sse_client.send(:connect_stream, latch)
329+
end
330+
allow(sse_client).to receive(:read_first_event).and_return(true)
331+
expect(thr2.status).to eq('run')
332+
333+
stop_workers
334+
end
335+
end
269336
end
270337

271338
private

0 commit comments

Comments
 (0)