Module: Bunny::JRuby::Socket

Includes:
Socket
Defined in:
lib/bunny/jruby/socket.rb

Overview

TCP socket extension that uses Socket#readpartial to avoid excessive CPU burn after some time. See issue #165.

Constant Summary

Constants included from Socket

Socket::READ_RETRY_EXCEPTION_CLASSES, Socket::WRITE_RETRY_EXCEPTION_CLASSES

Instance Attribute Summary

Attributes included from Socket

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Socket

#write_nonblock_fully

Class Method Details

.open(host, port, options = {}) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/bunny/jruby/socket.rb', line 11

def self.open(host, port, options = {})
  socket = ::Socket.tcp(host, port, nil, nil,
                        connect_timeout: options[:connect_timeout])
  if ::Socket.constants.include?('TCP_NODELAY') || ::Socket.constants.include?(:TCP_NODELAY)
    socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
  end
  socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options.fetch(:keepalive, true)
  socket.extend self
  socket.options = { :host => host, :port => port }.merge(options)
  socket
rescue Errno::ETIMEDOUT
  raise ClientTimeout
end

Instance Method Details

#read_fully(count, timeout = nil) ⇒ String

Reads given number of bytes with an optional timeout

Parameters:

  • count (Integer)

    How many bytes to read

  • timeout (Integer) (defaults to: nil)

    Timeout

Returns:

  • (String)

    Data read from the socket



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/bunny/jruby/socket.rb', line 32

def read_fully(count, timeout = nil)
  value = ''

  begin
    loop do
      value << read_nonblock(count - value.bytesize)
      break if value.bytesize >= count
    end
  rescue EOFError
    # JRuby specific fix via https://github.com/jruby/jruby/issues/1694#issuecomment-54873532
    IO.select([self], nil, nil, timeout)
    retry
  rescue *READ_RETRY_EXCEPTION_CLASSES
    if IO.select([self], nil, nil, timeout)
      retry
    else
      raise Timeout::Error, "IO timeout when reading #{count} bytes"
    end
  end

  value
end