Skip to content

Commit

Permalink
Better socket_timeout handling (#977)
Browse files Browse the repository at this point in the history
Better socket_timeout handling by using Socket's connect_timeout (available since Ruby 3.0) instead of Timeout when possible.
  • Loading branch information
mlarraz authored Dec 16, 2023
1 parent 7786984 commit 6165b94
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions lib/dalli/socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,40 @@ class TCP < TCPSocket
# options - supports enhanced logging in the case of a timeout
attr_accessor :options

def self.open(host, port, options = {})
Timeout.timeout(options[:socket_timeout]) do
sock = new(host, port)
if RUBY_VERSION >= '3.0'
def self.open(host, port, options = {})
sock = new(host, port, connect_timeout: options[:socket_timeout])
sock.options = { host: host, port: port }.merge(options)
init_socket_options(sock, options)

options[:ssl_context] ? wrapping_ssl_socket(sock, host, options[:ssl_context]) : sock
end
else
def self.open(host, port, options = {})
Timeout.timeout(options[:socket_timeout]) do
sock = new(host, port)
sock.options = { host: host, port: port }.merge(options)
init_socket_options(sock, options)

options[:ssl_context] ? wrapping_ssl_socket(sock, host, options[:ssl_context]) : sock
end
end
end

def self.init_socket_options(sock, options)
sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]

return unless options[:socket_timeout]

seconds, fractional = options[:socket_timeout].divmod(1)
microseconds = fractional * 1_000_000
timeval = [seconds, microseconds].pack('l_2')

sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVTIMEO, timeval)
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDTIMEO, timeval)
end

def self.wrapping_ssl_socket(tcp_socket, host, ssl_context)
Expand Down

0 comments on commit 6165b94

Please sign in to comment.