class HTTP::Timeout::Global

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/http/timeout/global.rb, line 11
def initialize(*args)
  super

  @timeout = @time_left = options.fetch(:global_timeout)
end

Public Instance Methods

<<(data)
Alias for: write
connect(socket_class, host, port, nodelay = false) click to toggle source
# File lib/http/timeout/global.rb, line 22
def connect(socket_class, host, port, nodelay = false)
  reset_timer
  ::Timeout.timeout(@time_left, TimeoutError) do
    @socket = socket_class.open(host, port)
    @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
  end

  log_time
end
connect_ssl() click to toggle source
# File lib/http/timeout/global.rb, line 32
def connect_ssl
  reset_timer

  begin
    @socket.connect_nonblock
  rescue IO::WaitReadable
    wait_readable_or_timeout
    retry
  rescue IO::WaitWritable
    wait_writable_or_timeout
    retry
  end
end
readpartial(size, buffer = nil) click to toggle source

Read from the socket

# File lib/http/timeout/global.rb, line 47
def readpartial(size, buffer = nil)
  perform_io { read_nonblock(size, buffer) }
end
reset_counter() click to toggle source

To future me: Don't remove this again, past you was smarter.

# File lib/http/timeout/global.rb, line 18
def reset_counter
  @time_left = @timeout
end
write(data) click to toggle source

Write to the socket

# File lib/http/timeout/global.rb, line 52
def write(data)
  perform_io { write_nonblock(data) }
end
Also aliased as: <<

Private Instance Methods

log_time() click to toggle source
# File lib/http/timeout/global.rb, line 108
def log_time
  @time_left -= (Time.now - @started)
  raise TimeoutError, "Timed out after using the allocated #{@timeout} seconds" if @time_left <= 0

  reset_timer
end
perform_io() { || ... } click to toggle source

Perform the given I/O operation with the given argument

# File lib/http/timeout/global.rb, line 69
def perform_io
  reset_timer

  loop do
    result = yield

    case result
    when :wait_readable then wait_readable_or_timeout
    when :wait_writable then wait_writable_or_timeout
    when NilClass       then return :eof
    else                return result
    end
  rescue IO::WaitReadable
    wait_readable_or_timeout
  rescue IO::WaitWritable
    wait_writable_or_timeout
  end
rescue EOFError
  :eof
end
read_nonblock(size, buffer = nil) click to toggle source
# File lib/http/timeout/global.rb, line 60
def read_nonblock(size, buffer = nil)
  @socket.read_nonblock(size, buffer, :exception => false)
end
reset_timer() click to toggle source

Due to the run/retry nature of nonblocking I/O, it's easier to keep track of time via method calls instead of a block to monitor.

# File lib/http/timeout/global.rb, line 104
def reset_timer
  @started = Time.now
end
wait_readable_or_timeout() click to toggle source

Wait for a socket to become readable

# File lib/http/timeout/global.rb, line 91
def wait_readable_or_timeout
  @socket.to_io.wait_readable(@time_left)
  log_time
end
wait_writable_or_timeout() click to toggle source

Wait for a socket to become writable

# File lib/http/timeout/global.rb, line 97
def wait_writable_or_timeout
  @socket.to_io.wait_writable(@time_left)
  log_time
end
write_nonblock(data) click to toggle source
# File lib/http/timeout/global.rb, line 64
def write_nonblock(data)
  @socket.write_nonblock(data, :exception => false)
end