class Moped::Node

Represents a client to a node in a server cluster.

@api private

Attributes

address[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

down_at[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

ip_address[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

options[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

peers[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

port[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

refreshed_at[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

resolved_address[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

timeout[R]

@attribute [r] address The address of the node. @attribute [r] #down_at The time the server node went down. @attribute [r] #ip_address The node's ip. @attribute [r] peers Other peers in the replica set. @attribute [r] port The connection port. @attribute [r] #resolved_address The host/port pair. @attribute [r] timeout The connection timeout. @attribute [r] options Additional options for the node (ssl).

Public Class Methods

new(address, options = {}) click to toggle source

Creat the new node.

@example Create the new node.

Node.new("127.0.0.1:27017")

@param [ String ] address The location of the server node. @param [ Hash ] options Additional options for the node (ssl)

@since 1.0.0

# File lib/moped/node.rb, line 241
def initialize(address, options = {})
  @address = address
  @options = options
  @timeout = options[:timeout] || 5
  @down_at = nil
  @refreshed_at = nil
  @primary = nil
  @secondary = nil
  resolve_address
end

Public Instance Methods

==(other) click to toggle source

Is this node equal to another?

@example Is the node equal to another.

node == other

@param [ Node ] other The other node.

@return [ true, false ] If the addresses are equal.

@since 1.0.0

# File lib/moped/node.rb, line 37
def ==(other)
  resolved_address == other.resolved_address
end
Also aliased as: eql?
apply_auth(credentials) click to toggle source

Apply the authentication details to this node.

@example Apply authentication.

node.apply_auth([ :db, "user", "pass" ])

@param [ Array<String> ] credentials The db, username, and password.

@return [ Node ] The authenticated node.

@since 1.0.0

# File lib/moped/node.rb, line 52
def apply_auth(credentials)
  unless auth == credentials
    logouts = auth.keys - credentials.keys
    logouts.each { |database| logout(database) }
    credentials.each do |database, (username, password)|
      login(database, username, password) unless auth[database] == [username, password]
    end
  end
  self
end
arbiter?() click to toggle source

Is the node an arbiter?

@example Is the node an arbiter?

node.arbiter?

@return [ true, false ] If the node is an arbiter.

@since 1.0.0

# File lib/moped/node.rb, line 336
def arbiter?
  @arbiter
end
auto_discovering?() click to toggle source

Is the cluster auto-discovering new nodes in the cluster?

@example Is the cluster auto discovering?

cluster.auto_discovering?

@return [ true, false ] If the cluster is auto discovering.

@since 2.0.0

# File lib/moped/node.rb, line 71
def auto_discovering?
  @auto_discovering ||= options[:auto_discover].nil? ? true : options[:auto_discover]
end
command(database, cmd, options = {}) click to toggle source

Execute a command against a database.

@example Execute a command.

node.command(database, { ping: 1 })

@param [ Database ] database The database to run the command on. @param [ Hash ] cmd The command to execute. @options [ Hash ] options The command options.

@raise [ OperationFailure ] If the command failed.

@return [ Hash ] The result of the command.

@since 1.0.0

# File lib/moped/node.rb, line 89
def command(database, cmd, options = {})
  operation = Protocol::Command.new(database, cmd, options)

  process(operation) do |reply|
    result = reply.documents.first
    if reply.command_failure?
      if reply.unauthorized? && auth.has_key?(database)
        login(database, *auth[database])
        return command(database, cmd, options)
      else
        raise Errors::OperationFailure.new(operation, result)
      end
    end
    result
  end
end
disconnect() click to toggle source

Force the node to disconnect from the server.

@return [ nil ] nil.

@since 1.2.0

# File lib/moped/node.rb, line 111
def disconnect
  auth.clear
  connection.disconnect
end
down?() click to toggle source

Is the node down?

@example Is the node down?

node.down?

@return [ Time, nil ] The time the node went down, or nil if up.

@since 1.0.0

# File lib/moped/node.rb, line 124
def down?
  @down_at
end
ensure_connected() { || ... } click to toggle source

Yields the block if a connection can be established, retrying when a connection error is raised.

@example Ensure we are connection.

node.ensure_connected do
  #...
end

@raises [ ConnectionFailure ] When a connection cannot be established.

@return [ nil ] nil.

@since 1.0.0

# File lib/moped/node.rb, line 141
def ensure_connected
  # Don't run the reconnection login if we're already inside an
  # +ensure_connected+ block.
  return yield if Threaded.executing?(:connection)
  Threaded.begin(:connection)
  retry_on_failure = true

  begin
    connect unless connected?
    yield
  rescue Errors::PotentialReconfiguration => e
    if e.reconfiguring_replica_set?
      raise Errors::ReplicaSetReconfigured.new(e.command, e.details)
    end
    raise
  rescue Errors::DoNotDisconnect
    # These exceptions are "expected" in the normal course of events, and
    # don't necessitate disconnecting.
    raise
  rescue Errors::ConnectionFailure
    disconnect
    if retry_on_failure
      # Maybe there was a hiccup -- try reconnecting one more time
      retry_on_failure = false
      retry
    else
      # Nope, we failed to connect twice. Flag the node as down and re-raise
      # the exception.
      down!
      raise
    end
  rescue
    # Looks like we got an unexpected error, so we'll clean up the connection
    # and re-raise the exception.
    disconnect
    raise $!.extend(Errors::SocketError)
  end
ensure
  Threaded.end(:connection)
end
ensure_primary() { || ... } click to toggle source

Set a flag on the node for the duration of provided block so that an exception is raised if the node is no longer the primary node.

@example Ensure this node is primary.

node.ensure_primary do
  #...
end

@return [ nil ] nil.

@since 1.0.0

# File lib/moped/node.rb, line 193
def ensure_primary
  Threaded.begin(:ensure_primary)
  yield
ensure
  Threaded.end(:ensure_primary)
end
eql?(other) click to toggle source
Alias for: ==
get_more(database, collection, cursor_id, limit) click to toggle source

Execute a get more operation on the node.

@example Execute a get more.

node.get_more(database, collection, 12345, -1)

@param [ Database ] database The database to get more from. @param [ Collection ] collection The collection to get more from. @param [ Integer ] cursor_id The id of the cursor on the server. @param [ Integer ] limit The number of documents to limit. @raise [ CursorNotFound ] if the cursor has been killed

@return [ Message ] The result of the operation.

@since 1.0.0

# File lib/moped/node.rb, line 214
def get_more(database, collection, cursor_id, limit)
  reply = process(Protocol::GetMore.new(database, collection, cursor_id, limit))
  raise Moped::Errors::CursorNotFound.new("GET MORE", cursor_id) if reply.cursor_not_found?
  reply
end
hash() click to toggle source

Get the hash identifier for the node.

@example Get the hash identifier.

node.hash

@return [ Integer ] The hash identifier.

@since 1.0.0

# File lib/moped/node.rb, line 228
def hash
  resolved_address.hash
end
insert(database, collection, documents, options = {}) click to toggle source

Insert documents into the database.

@example Insert documents.

node.insert(database, collection, [{ name: "Tool" }])

@param [ Database ] database The database to insert to. @param [ Collection ] collection The collection to insert to. @param [ Array<Hash> ] documents The documents to insert.

@return [ Message ] The result of the operation.

@since 1.0.0

# File lib/moped/node.rb, line 264
def insert(database, collection, documents, options = {})
  process(Protocol::Insert.new(database, collection, documents, options))
end
inspect() click to toggle source

Get the node as a nice formatted string.

@example Inspect the node.

node.inspect

@return [ String ] The string inspection.

@since 1.0.0

# File lib/moped/node.rb, line 485
def inspect
  "<#{self.class.name} resolved_address=#{@resolved_address.inspect}>"
end
kill_cursors(cursor_ids) click to toggle source

Kill all provided cursors on the node.

@example Kill all the provided cursors.

node.kill_cursors([ 12345 ])

@param [ Array<Integer> ] cursor_ids The cursor ids.

@return [ Message ] The result of the operation.

@since 1.0.0

# File lib/moped/node.rb, line 278
def kill_cursors(cursor_ids)
  process(Protocol::KillCursors.new(cursor_ids))
end
needs_refresh?(time) click to toggle source

Does the node need to be refreshed?

@example Does the node require refreshing?

node.needs_refresh?(time)

@param [ Time ] time The next referesh time.

@return [ true, false] Whether the node needs to be refreshed.

@since 1.0.0

# File lib/moped/node.rb, line 292
def needs_refresh?(time)
  !refreshed_at || refreshed_at < time
end
passive?() click to toggle source

Is the node passive?

@example Is the node passive?

node.passive?

@return [ true, false ] If the node is passive.

@since 1.0.0

# File lib/moped/node.rb, line 348
def passive?
  @passive
end
pipeline() { || ... } click to toggle source

Execute a pipeline of commands, for example a safe mode persist.

@example Execute a pipeline.

node.pipeline do
  #...
end

@return [ nil ] nil.

@since 1.0.0

# File lib/moped/node.rb, line 306
def pipeline
  Threaded.begin(:pipeline)
  begin
    yield
  ensure
    Threaded.end(:pipeline)
  end
  flush unless Threaded.executing?(:pipeline)
end
primary?() click to toggle source

Is the node the replica set primary?

@example Is the node the primary?

node.primary?

@return [ true, false ] If the node is the primary.

@since 1.0.0

# File lib/moped/node.rb, line 324
def primary?
  @primary
end
query(database, collection, selector, options = {}) click to toggle source

Execute a query on the node.

@example Execute a query.

node.query(database, collection, { name: "Tool" })

@param [ Database ] database The database to query from. @param [ Collection ] collection The collection to query from. @param [ Hash ] selector The query selector. @param [ Hash ] options The query options.

@raise [ QueryFailure ] If the query had an error.

@return [ Message ] The result of the operation.

@since 1.0.0

# File lib/moped/node.rb, line 367
def query(database, collection, selector, options = {})
  operation = Protocol::Query.new(database, collection, selector, options)

  process(operation) do |reply|
    if reply.query_failed?
      if reply.unauthorized? && auth.has_key?(database)
        # If we got here, most likely this is the case of Moped
        # authenticating successfully against the node originally, but the
        # node has been reset or gone down and come back up. The most
        # common case here is a rs.stepDown() which will reinitialize the
        # connection. In this case we need to requthenticate and try again,
        # otherwise we'll just raise the error to the user.
        login(database, *auth[database])
        return query(database, collection, selector, options)
      else
        raise Errors::QueryFailure.new(operation, reply.documents.first)
      end
    end
    reply
  end
end
refresh() click to toggle source

Refresh information about the node, such as it's status in the replica set and it's known peers.

@example Refresh the node.

node.refresh

@raise [ ConnectionFailure ] If the node cannot be reached.

@raise [ ReplicaSetReconfigured ] If the node is no longer a primary node and

refresh was called within an +#ensure_primary+ block.

@return [ nil ] nil.

@since 1.0.0

# File lib/moped/node.rb, line 403
def refresh
  if resolve_address
    begin
      @refreshed_at = Time.now
      info = command("admin", ismaster: 1)
      primary = true   if info["ismaster"]
      secondary = true if info["secondary"]
      generate_peers(info)

      @primary, @secondary = primary, secondary
      @arbiter = info["arbiterOnly"]
      @passive = info["passive"]

      if !primary && Threaded.executing?(:ensure_primary)
        raise Errors::ReplicaSetReconfigured.new("#{inspect} is no longer the primary node.", {})
      elsif !primary && !secondary
        # not primary or secondary so mark it as down, since it's probably
        # a recovering node withing the replica set
        down!
      end
    rescue Timeout::Error
      @peers = []
      down!
    end
  end
end
remove(database, collection, selector, options = {}) click to toggle source

Execute a remove command for the provided selector.

@example Remove documents.

node.remove(database, collection, { name: "Tool" })

@param [ Database ] database The database to remove from. @param [ Collection ] collection The collection to remove from. @param [ Hash ] selector The query selector. @param [ Hash ] options The remove options.

@return [ Message ] The result of the operation.

@since 1.0.0

# File lib/moped/node.rb, line 443
def remove(database, collection, selector, options = {})
  process(Protocol::Delete.new(database, collection, selector, options))
end
secondary?() click to toggle source

Is the node a replica set secondary?

@example Is the node a secondary?

node.secondary?

@return [ true, false ] If the node is a secondary.

@since 1.0.0

# File lib/moped/node.rb, line 455
def secondary?
  @secondary
end
update(database, collection, selector, change, options = {}) click to toggle source

Execute an update command for the provided selector.

@example Update documents.

node.update(database, collection, { name: "Tool" }, { likes: 1000 })

@param [ Database ] database The database to update. @param [ Collection ] collection The collection to update. @param [ Hash ] selector The query selector. @param [ Hash ] change The updates. @param [ Hash ] options The update options.

@return [ Message ] The result of the operation.

@since 1.0.0

# File lib/moped/node.rb, line 473
def update(database, collection, selector, change, options = {})
  process(Protocol::Update.new(database, collection, selector, change, options))
end