class EM::Voldemort::Connection

TCP connection to one Voldemort node. The connection can be used to access multiple stores. Automatically reconnects if the connection is lost, but does not automatically retry failed requests (that is the cluster’s job).

Constants

DEFAULT_PROTOCOL
REQUEST_TIMEOUT
STATUS_CHECK_PERIOD

Attributes

health[R]
host[R]
logger[R]
node_id[R]
port[R]
protocol[R]

Public Class Methods

new(options={}) click to toggle source
# File lib/em-voldemort/connection.rb, line 12
def initialize(options={})
  @host = options[:host] or raise ArgumentError, "#{self.class.name} requires :host"
  @port = options[:port] or raise ArgumentError, "#{self.class.name} requires :port"
  @node_id = options[:node_id]
  @protocol = options[:protocol] || DEFAULT_PROTOCOL
  @logger = options[:logger] || Logger.new($stdout)
  @health = :good
end

Public Instance Methods

close() click to toggle source

Waits for the outstanding request (if any) to complete, then gracefully shuts down the connection. Returns a deferrable that succeeds once the connection is closed (never fails).

# File lib/em-voldemort/connection.rb, line 38
def close
  return @closing_deferrable if @closing_deferrable
  @closing_deferrable = EM::DefaultDeferrable.new
  @timer.cancel

  if @handler
    @handler.close_gracefully
  else
    @closing_deferrable.succeed
  end

  @handler = FailHandler.new(self)
  @health = :bad
  @closing_deferrable
end
connect() click to toggle source

Establishes a connection to the node. Calling connect is optional, since it also happens automatically when you start making requests.

# File lib/em-voldemort/connection.rb, line 23
def connect
  force_connect unless @handler
end
connection_closed(handler, reason=nil) click to toggle source

Called by the connection handler when the connection is closed for any reason (closed by us, closed by peer, rejected, timeout etc). Do not call from application code.

# File lib/em-voldemort/connection.rb, line 56
def connection_closed(handler, reason=nil)
  logger.info ["Connection to Voldemort node #{host}:#{port} closed", reason].compact.join(': ')
  @handler = FailHandler.new(self) if handler.equal? @handler
  @health = :bad
  @closing_deferrable.succeed if @closing_deferrable
end
send_request(request) click to toggle source

Sends a request to the node, given as a binary string (not including the request size prefix). Establishes a connection if necessary. If a request is already in progress, this request is queued up. Returns a deferrable that succeeds with the node’s response (again without the size prefix), or fails if there was a network-level error.

# File lib/em-voldemort/connection.rb, line 31
def send_request(request)
  connect
  @handler.enqueue_request(request)
end

Private Instance Methods

force_connect() click to toggle source
# File lib/em-voldemort/connection.rb, line 82
def force_connect
  @timer ||= setup_status_check_timer(&method(:status_check))
  @handler = EM.connect(host, port, Handler, self)
  @handler.in_flight.callback { @health = :good } # restore health if protocol negotiation succeeded
rescue EventMachine::ConnectionError => e
  # A synchronous exception is typically thrown on DNS resolution failure
  logger.warn "Cannot connect to Voldemort node: #{e.class.name}: #{e.message}"
  connection_closed(@handler)
  @handler = FailHandler.new(self)
end
setup_status_check_timer() { || ... } click to toggle source
# File lib/em-voldemort/connection.rb, line 65
def setup_status_check_timer
  EM.add_periodic_timer(STATUS_CHECK_PERIOD) { yield }
end
status_check() click to toggle source
# File lib/em-voldemort/connection.rb, line 69
def status_check
  if @closing_deferrable
    # Do nothing (don't reconnect once we've been asked to shut down).
  elsif !@handler || @handler.is_a?(FailHandler)
    # Connect for the first time, or reconnect after failure.
    force_connect
  elsif @handler.in_flight && Time.now - @handler.last_request >= REQUEST_TIMEOUT
    # Request timed out. Pronounce the connection dead, and reconnect.
    @handler.close_connection
    force_connect
  end
end