Description
Version 8.11.0 introduced a TypeError: class or module required in SSEClient#close that fires on every SSE socket close. The error is caught by the rescue StandardError block so it doesn't crash the process, but it generates a high volume of error log entries (~400/day in our production environment across multiple services consuming the SDK).
We had to pin splitclient-rb < 8.11.0 in our wrapper gem to avoid this.
SDK Version
- Affected: 8.11.0, master
- Not affected: 8.10.1 and earlier
Root Cause
In lib/splitclient-rb/sse/event_source/client.rb, line 50 of the close method:
@config.logger.debug("SSEClient socket state #{@socket.state}") if @socket.is_a? OpenSSL::SSL::SSLSocket && @config.debug_enabled
Without explicit parentheses, Ruby parses the is_a? argument as:
@socket.is_a?(OpenSSL::SSL::SSLSocket && @config.debug_enabled)
Since OpenSSL::SSL::SSLSocket is truthy, && evaluates and returns the right operand (@config.debug_enabled, a boolean). Then is_a?(true) or is_a?(false) raises TypeError: class or module required.
Note that line 48 has a similar is_a? call but without &&, so it parses correctly:
@socket.sync_close = true if @socket.is_a? OpenSSL::SSL::SSLSocket # works fine
Suggested Fix
Add explicit parentheses:
@config.logger.debug("SSEClient socket state #{@socket.state}") if @socket.is_a?(OpenSSL::SSL::SSLSocket) && @config.debug_enabled
Happy to submit a PR for this if that's helpful.
Description
Version 8.11.0 introduced a
TypeError: class or module requiredinSSEClient#closethat fires on every SSE socket close. The error is caught by therescue StandardErrorblock so it doesn't crash the process, but it generates a high volume of error log entries (~400/day in our production environment across multiple services consuming the SDK).We had to pin
splitclient-rb < 8.11.0in our wrapper gem to avoid this.SDK Version
Root Cause
In
lib/splitclient-rb/sse/event_source/client.rb, line 50 of theclosemethod:Without explicit parentheses, Ruby parses the
is_a?argument as:Since
OpenSSL::SSL::SSLSocketis truthy,&&evaluates and returns the right operand (@config.debug_enabled, a boolean). Thenis_a?(true)oris_a?(false)raisesTypeError: class or module required.Note that line 48 has a similar
is_a?call but without&&, so it parses correctly:Suggested Fix
Add explicit parentheses:
Happy to submit a PR for this if that's helpful.