11# frozen_string_literal: false
22
3- require 'socketry'
3+ require 'socket'
4+ require 'openssl'
45require 'uri'
6+ require 'timeout'
57
68module SplitIoClient
79 module SSE
@@ -36,12 +38,12 @@ def initialize(config,
3638
3739 def close ( status = nil )
3840 unless connected?
39- @config . logger . error ( 'SSEClient already disconected.' ) if @config . debug_enabled
41+ log_if_debug ( 'SSEClient already disconected.' , 3 )
4042 return
4143 end
4244
4345 @connected . make_false
44- @socket & .close
46+ @socket . close
4547 push_status ( status )
4648 rescue StandardError => e
4749 @config . logger . error ( "SSEClient close Error: #{ e . inspect } " )
@@ -74,30 +76,40 @@ def connected?
7476
7577 def connect_thread ( latch )
7678 @config . threads [ :connect_stream ] = Thread . new do
77- @config . logger . info ( 'Starting connect_stream thread ...' ) if @config . debug_enabled
79+ log_if_debug ( 'Starting connect_stream thread ...' , 2 )
7880 new_status = connect_stream ( latch )
7981 push_status ( new_status )
80- @config . logger . info ( 'connect_stream thread finished.' ) if @config . debug_enabled
82+ log_if_debug ( 'connect_stream thread finished.' , 2 )
8183 end
8284 end
8385
8486 def connect_stream ( latch )
8587 return Constants ::PUSH_NONRETRYABLE_ERROR unless socket_write ( latch )
86-
8788 while connected? || @first_event . value
8889 begin
89- partial_data = @socket . readpartial ( 10_000 , timeout : @read_timeout )
90-
90+ partial_data = ""
91+ Timeout ::timeout @read_timeout do
92+ partial_data = @socket . readpartial ( 10_000 )
93+ end
9194 read_first_event ( partial_data , latch )
9295
9396 raise 'eof exception' if partial_data == :eof
97+ rescue Timeout ::Error => e
98+ log_if_debug ( "SSE read operation timed out!: #{ e . inspect } " , 3 )
99+ return Constants ::PUSH_RETRYABLE_ERROR
100+ rescue EOFError
101+ raise 'eof exception'
102+ rescue Errno ::EAGAIN => e
103+ log_if_debug ( "SSE client transient error: #{ e . inspect } " , 1 )
104+ IO . select ( [ tcp_socket ] )
105+ retry
94106 rescue Errno ::EBADF , IOError => e
95- @config . logger . error ( e . inspect ) if @config . debug_enabled
107+ log_if_debug ( e . inspect , 3 )
96108 return nil
97109 rescue StandardError => e
98110 return nil if ENV [ 'SPLITCLIENT_ENV' ] == 'test'
99111
100- @config . logger . error ( "Error reading partial data: #{ e . inspect } " ) if @config . debug_enabled
112+ log_if_debug ( "Error reading partial data: #{ e . inspect } " , 3 )
101113 return Constants ::PUSH_RETRYABLE_ERROR
102114 end
103115
@@ -109,10 +121,10 @@ def connect_stream(latch)
109121 def socket_write ( latch )
110122 @first_event . make_true
111123 @socket = socket_connect
112- @socket . write ( build_request ( @uri ) )
124+ @socket . puts ( build_request ( @uri ) )
113125 true
114126 rescue StandardError => e
115- @config . logger . error ( "Error during connecting to #{ @uri . host } . Error: #{ e . inspect } " )
127+ log_if_debug ( "Error during connecting to #{ @uri . host } . Error: #{ e . inspect } " , 3 )
116128 latch . count_down
117129 false
118130 end
@@ -138,15 +150,28 @@ def read_first_event(data, latch)
138150 end
139151
140152 def socket_connect
141- return Socketry ::SSL ::Socket . connect ( @uri . host , @uri . port ) if @uri . scheme . casecmp ( 'https' ) . zero?
153+ tcp_socket = TCPSocket . new ( @uri . host , @uri . port )
154+ if @uri . scheme . casecmp ( 'https' ) . zero?
155+ begin
156+ ssl_context = OpenSSL ::SSL ::SSLContext . new
157+ ssl_socket = OpenSSL ::SSL ::SSLSocket . new ( tcp_socket , ssl_context )
158+ ssl_socket . hostname = @uri . host
159+ ssl_socket . connect
160+ return ssl_socket . connect
161+ rescue Exception => e
162+ @config . logger . error ( "socket connect error: #{ e . inspect } " )
163+ puts e . inspect
164+ return nil
165+ end
166+ end
142167
143- Socketry :: TCP :: Socket . connect ( @uri . host , @uri . port )
168+ tcp_socket
144169 end
145170
146171 def process_data ( partial_data )
147172 return if partial_data . nil? || partial_data == KEEP_ALIVE_RESPONSE
148173
149- @config . logger . debug ( "Event partial data: #{ partial_data } " ) if @config . debug_enabled
174+ log_if_debug ( "Event partial data: #{ partial_data } " , 1 )
150175 events = @event_parser . parse ( partial_data )
151176 events . each { |event | process_event ( event ) }
152177 rescue StandardError => e
@@ -162,7 +187,7 @@ def build_request(uri)
162187 req << "SplitSDKMachineName: #{ @config . machine_name } \r \n "
163188 req << "SplitSDKClientKey: #{ @api_key . split ( // ) . last ( 4 ) . join } \r \n " unless @api_key . nil?
164189 req << "Cache-Control: no-cache\r \n \r \n "
165- @config . logger . debug ( "Request info: #{ req } " ) if @config . debug_enabled
190+ log_if_debug ( "Request info: #{ req } " , 1 )
166191 req
167192 end
168193
@@ -200,6 +225,19 @@ def push_status(status)
200225 @config . logger . debug ( "Pushing new sse status: #{ status } " )
201226 @status_queue . push ( status )
202227 end
228+
229+ def log_if_debug ( text , level )
230+ if @config . debug_enabled
231+ case level
232+ when 1
233+ @config . logger . debug ( text )
234+ when 2
235+ @config . logger . info ( text )
236+ else
237+ @config . logger . error ( text )
238+ end
239+ end
240+ end
203241 end
204242 end
205243 end
0 commit comments