Class: Moped::Node Private

Inherits:
Object show all
Defined in:
lib/moped/node.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Represents a client to a node in a server cluster.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(address, options = {}) ⇒ Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creat the new node.

Examples:

Create the new node.

Node.new("127.0.0.1:27017")

Parameters:

  • address (String)

    The location of the server node.

  • options (Hash) (defaults to: {})

    Additional options for the node (ssl)

Since:

  • 1.0.0



243
244
245
246
247
248
249
250
251
252
# File 'lib/moped/node.rb', line 243

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

Instance Attribute Details

#addressObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def address
  @address
end

#address The address of the node.(Theaddressofthenode.) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#down_atObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def down_at
  @down_at
end

#down_at The time the server node went down.(Thetimetheservernodewentdown.) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#ip_addressObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def ip_address
  @ip_address
end

#ip_address The node's ip.(Thenode's ip.) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#optionsObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def options
  @options
end

#options Additional options for the node (ssl).(Additionaloptions) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#peersObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def peers
  @peers
end

#peers Other peers in the replica set.(Otherpeers) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#portObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def port
  @port
end

#port The connection port.(Theconnectionport.) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#refreshed_atObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def refreshed_at
  @refreshed_at
end

#resolved_addressObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def resolved_address
  @resolved_address
end

#resolved_address The host/port pair.(Thehost/portpair.) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

#timeoutObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
# File 'lib/moped/node.rb', line 16

def timeout
  @timeout
end

#timeout The connection timeout.(Theconnectiontimeout.) ⇒ Object (readonly)



16
17
18
19
20
21
22
23
24
25
# File 'lib/moped/node.rb', line 16

attr_reader \
:address,
:down_at,
:ip_address,
:peers,
:port,
:resolved_address,
:timeout,
:options,
:refreshed_at

Instance Method Details

#==(other) ⇒ true, false Also known as: eql?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Is this node equal to another?

Examples:

Is the node equal to another.

node == other

Parameters:

  • other (Node)

    The other node.

Returns:

  • (true, false)

    If the addresses are equal.

Since:

  • 1.0.0



37
38
39
# File 'lib/moped/node.rb', line 37

def ==(other)
  resolved_address == other.resolved_address
end

#apply_auth(credentials) ⇒ Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Apply the authentication details to this node.

Examples:

Apply authentication.

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

Parameters:

  • credentials (Array<String>)

    The db, username, and password.

Returns:

  • (Node)

    The authenticated node.

Since:

  • 1.0.0



52
53
54
55
56
57
58
59
60
61
# 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)|
      (database, username, password) unless auth[database] == [username, password]
    end
  end
  self
end

#arbiter?true, false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Is the node an arbiter?

Examples:

Is the node an arbiter?

node.arbiter?

Returns:

  • (true, false)

    If the node is an arbiter.

Since:

  • 1.0.0



338
339
340
# File 'lib/moped/node.rb', line 338

def arbiter?
  @arbiter
end

#auto_discovering?true, false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

Examples:

Is the cluster auto discovering?

cluster.auto_discovering?

Returns:

  • (true, false)

    If the cluster is auto discovering.

Since:

  • 2.0.0



71
72
73
# 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 = {}) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a command against a database.

Examples:

Execute a command.

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

Parameters:

  • database (Database)

    The database to run the command on.

  • cmd (Hash)

    The command to execute.

Returns:

  • (Hash)

    The result of the command.

Raises:

  • (OperationFailure)

    If the command failed.

Since:

  • 1.0.0



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# 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)
        (database, *auth[database])
        result = command(database, cmd, options)
      else
        raise Errors::OperationFailure.new(operation, result)
      end
    end
    result
  end
end

#disconnectnil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Force the node to disconnect from the server.

Returns:

  • (nil)

    nil.

Since:

  • 1.2.0



111
112
113
114
# File 'lib/moped/node.rb', line 111

def disconnect
  auth.clear
  connection.disconnect
end

#down?Time?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Is the node down?

Examples:

Is the node down?

node.down?

Returns:

  • (Time, nil)

    The time the node went down, or nil if up.

Since:

  • 1.0.0



124
125
126
# File 'lib/moped/node.rb', line 124

def down?
  @down_at
end

#ensure_connectednil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

Examples:

Ensure we are connection.

node.ensure_connected do
  #...
end

Returns:

  • (nil)

    nil.

Since:

  • 1.0.0



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# 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)
    elsif e.connection_failure?
      raise Errors::ConnectionFailure.new(e.inspect)
    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_primarynil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.

Examples:

Ensure this node is primary.

node.ensure_primary do
  #...
end

Returns:

  • (nil)

    nil.

Since:

  • 1.0.0



195
196
197
198
199
200
# File 'lib/moped/node.rb', line 195

def ensure_primary
  Threaded.begin(:ensure_primary)
  yield
ensure
  Threaded.end(:ensure_primary)
end

#get_more(database, collection, cursor_id, limit) ⇒ Message

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a get more operation on the node.

Examples:

Execute a get more.

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

Parameters:

  • database (Database)

    The database to get more from.

  • collection (Collection)

    The collection to get more from.

  • cursor_id (Integer)

    The id of the cursor on the server.

  • limit (Integer)

    The number of documents to limit.

Returns:

  • (Message)

    The result of the operation.

Raises:

  • (CursorNotFound)

    if the cursor has been killed

Since:

  • 1.0.0



216
217
218
219
220
# File 'lib/moped/node.rb', line 216

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

#hashInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get the hash identifier for the node.

Examples:

Get the hash identifier.

node.hash

Returns:

  • (Integer)

    The hash identifier.

Since:

  • 1.0.0



230
231
232
# File 'lib/moped/node.rb', line 230

def hash
  resolved_address.hash
end

#insert(database, collection, documents, options = {}) ⇒ Message

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Insert documents into the database.

Examples:

Insert documents.

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

Parameters:

  • database (Database)

    The database to insert to.

  • collection (Collection)

    The collection to insert to.

  • documents (Array<Hash>)

    The documents to insert.

Returns:

  • (Message)

    The result of the operation.

Since:

  • 1.0.0



266
267
268
# File 'lib/moped/node.rb', line 266

def insert(database, collection, documents, options = {})
  process(Protocol::Insert.new(database, collection, documents, options))
end

#inspectString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get the node as a nice formatted string.

Examples:

Inspect the node.

node.inspect

Returns:

  • (String)

    The string inspection.

Since:

  • 1.0.0



487
488
489
# File 'lib/moped/node.rb', line 487

def inspect
  "<#{self.class.name} resolved_address=#{@resolved_address.inspect}>"
end

#kill_cursors(cursor_ids) ⇒ Message

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Kill all provided cursors on the node.

Examples:

Kill all the provided cursors.

node.kill_cursors([ 12345 ])

Parameters:

Returns:

  • (Message)

    The result of the operation.

Since:

  • 1.0.0



280
281
282
# File 'lib/moped/node.rb', line 280

def kill_cursors(cursor_ids)
  process(Protocol::KillCursors.new(cursor_ids))
end

#needs_refresh?(time) ⇒ true, false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Does the node need to be refreshed?

Examples:

Does the node require refreshing?

node.needs_refresh?(time)

Parameters:

  • time (Time)

    The next referesh time.

Returns:

  • (true, false)

    Whether the node needs to be refreshed.

Since:

  • 1.0.0



294
295
296
# File 'lib/moped/node.rb', line 294

def needs_refresh?(time)
  !refreshed_at || refreshed_at < time
end

#passive?true, false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Is the node passive?

Examples:

Is the node passive?

node.passive?

Returns:

  • (true, false)

    If the node is passive.

Since:

  • 1.0.0



350
351
352
# File 'lib/moped/node.rb', line 350

def passive?
  @passive
end

#pipelinenil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

Examples:

Execute a pipeline.

node.pipeline do
  #...
end

Returns:

  • (nil)

    nil.

Since:

  • 1.0.0



308
309
310
311
312
313
314
315
316
# File 'lib/moped/node.rb', line 308

def pipeline
  Threaded.begin(:pipeline)
  begin
    yield
  ensure
    Threaded.end(:pipeline)
  end
  flush unless Threaded.executing?(:pipeline)
end

#primary?true, false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Is the node the replica set primary?

Examples:

Is the node the primary?

node.primary?

Returns:

  • (true, false)

    If the node is the primary.

Since:

  • 1.0.0



326
327
328
# File 'lib/moped/node.rb', line 326

def primary?
  @primary
end

#query(database, collection, selector, options = {}) ⇒ Message

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a query on the node.

Examples:

Execute a query.

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

Parameters:

  • database (Database)

    The database to query from.

  • collection (Collection)

    The collection to query from.

  • selector (Hash)

    The query selector.

  • options (Hash) (defaults to: {})

    The query options.

Returns:

  • (Message)

    The result of the operation.

Raises:

  • (QueryFailure)

    If the query had an error.

Since:

  • 1.0.0



369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/moped/node.rb', line 369

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.
        (database, *auth[database])
        reply = query(database, collection, selector, options)
      else
        raise Errors::QueryFailure.new(operation, reply.documents.first)
      end
    end
    reply
  end
end

#refreshnil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

Examples:

Refresh the node.

node.refresh

Returns:

  • (nil)

    nil.

Raises:

  • (ConnectionFailure)

    If the node cannot be reached.

  • (ReplicaSetReconfigured)

    If the node is no longer a primary node and refresh was called within an #ensure_primary block.

Since:

  • 1.0.0



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/moped/node.rb', line 405

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 = {}) ⇒ Message

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a remove command for the provided selector.

Examples:

Remove documents.

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

Parameters:

  • database (Database)

    The database to remove from.

  • collection (Collection)

    The collection to remove from.

  • selector (Hash)

    The query selector.

  • options (Hash) (defaults to: {})

    The remove options.

Returns:

  • (Message)

    The result of the operation.

Since:

  • 1.0.0



445
446
447
# File 'lib/moped/node.rb', line 445

def remove(database, collection, selector, options = {})
  process(Protocol::Delete.new(database, collection, selector, options))
end

#secondary?true, false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Is the node a replica set secondary?

Examples:

Is the node a secondary?

node.secondary?

Returns:

  • (true, false)

    If the node is a secondary.

Since:

  • 1.0.0



457
458
459
# File 'lib/moped/node.rb', line 457

def secondary?
  @secondary
end

#update(database, collection, selector, change, options = {}) ⇒ Message

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute an update command for the provided selector.

Examples:

Update documents.

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

Parameters:

  • database (Database)

    The database to update.

  • collection (Collection)

    The collection to update.

  • selector (Hash)

    The query selector.

  • change (Hash)

    The updates.

  • options (Hash) (defaults to: {})

    The update options.

Returns:

  • (Message)

    The result of the operation.

Since:

  • 1.0.0



475
476
477
# File 'lib/moped/node.rb', line 475

def update(database, collection, selector, change, options = {})
  process(Protocol::Update.new(database, collection, selector, change, options))
end