moped 1.5.3 → 2.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of moped might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -5
- data/README.md +1 -1
- data/lib/moped.rb +10 -13
- data/lib/moped/address.rb +56 -0
- data/lib/moped/authenticatable.rb +89 -0
- data/lib/moped/cluster.rb +169 -136
- data/lib/moped/collection.rb +53 -19
- data/lib/moped/connection.rb +69 -10
- data/lib/moped/connection/manager.rb +49 -0
- data/lib/moped/connection/pool.rb +198 -0
- data/lib/moped/connection/queue.rb +93 -0
- data/lib/moped/connection/reaper.rb +52 -0
- data/lib/moped/connection/socket.rb +4 -0
- data/lib/moped/connection/socket/connectable.rb +169 -0
- data/lib/moped/connection/socket/ssl.rb +52 -0
- data/lib/moped/connection/socket/tcp.rb +25 -0
- data/lib/moped/connection/sockets.rb +4 -0
- data/lib/moped/cursor.rb +3 -5
- data/lib/moped/database.rb +18 -24
- data/lib/moped/errors.rb +35 -6
- data/lib/moped/executable.rb +96 -0
- data/lib/moped/failover.rb +41 -0
- data/lib/moped/failover/disconnect.rb +31 -0
- data/lib/moped/failover/ignore.rb +29 -0
- data/lib/moped/failover/reconfigure.rb +34 -0
- data/lib/moped/failover/retry.rb +37 -0
- data/lib/moped/indexes.rb +4 -1
- data/lib/moped/instrumentable.rb +39 -0
- data/lib/moped/instrumentable/log.rb +43 -0
- data/lib/moped/instrumentable/noop.rb +31 -0
- data/lib/moped/loggable.rb +110 -0
- data/lib/moped/node.rb +316 -297
- data/lib/moped/operation.rb +3 -0
- data/lib/moped/operation/read.rb +62 -0
- data/lib/moped/operation/write.rb +57 -0
- data/lib/moped/protocol/command.rb +65 -4
- data/lib/moped/protocol/commands/authenticate.rb +1 -2
- data/lib/moped/protocol/delete.rb +16 -0
- data/lib/moped/protocol/get_more.rb +102 -31
- data/lib/moped/protocol/insert.rb +17 -0
- data/lib/moped/protocol/message.rb +44 -46
- data/lib/moped/protocol/query.rb +175 -92
- data/lib/moped/protocol/reply.rb +19 -8
- data/lib/moped/protocol/update.rb +18 -0
- data/lib/moped/query.rb +43 -17
- data/lib/moped/read_preference.rb +49 -0
- data/lib/moped/read_preference/nearest.rb +55 -0
- data/lib/moped/read_preference/primary.rb +60 -0
- data/lib/moped/read_preference/primary_preferred.rb +55 -0
- data/lib/moped/read_preference/secondary.rb +50 -0
- data/lib/moped/read_preference/secondary_preferred.rb +53 -0
- data/lib/moped/read_preference/selectable.rb +79 -0
- data/lib/moped/readable.rb +55 -0
- data/lib/moped/session.rb +122 -70
- data/lib/moped/{mongo_uri.rb → uri.rb} +75 -31
- data/lib/moped/version.rb +1 -1
- data/lib/moped/write_concern.rb +33 -0
- data/lib/moped/write_concern/propagate.rb +38 -0
- data/lib/moped/write_concern/unverified.rb +28 -0
- metadata +79 -44
- data/lib/moped/bson.rb +0 -45
- data/lib/moped/bson/binary.rb +0 -137
- data/lib/moped/bson/code.rb +0 -112
- data/lib/moped/bson/document.rb +0 -41
- data/lib/moped/bson/extensions.rb +0 -91
- data/lib/moped/bson/extensions/array.rb +0 -37
- data/lib/moped/bson/extensions/boolean.rb +0 -16
- data/lib/moped/bson/extensions/false_class.rb +0 -19
- data/lib/moped/bson/extensions/float.rb +0 -22
- data/lib/moped/bson/extensions/hash.rb +0 -39
- data/lib/moped/bson/extensions/integer.rb +0 -36
- data/lib/moped/bson/extensions/nil_class.rb +0 -19
- data/lib/moped/bson/extensions/object.rb +0 -11
- data/lib/moped/bson/extensions/regexp.rb +0 -38
- data/lib/moped/bson/extensions/string.rb +0 -45
- data/lib/moped/bson/extensions/symbol.rb +0 -33
- data/lib/moped/bson/extensions/time.rb +0 -23
- data/lib/moped/bson/extensions/true_class.rb +0 -19
- data/lib/moped/bson/max_key.rb +0 -51
- data/lib/moped/bson/min_key.rb +0 -51
- data/lib/moped/bson/object_id.rb +0 -301
- data/lib/moped/bson/timestamp.rb +0 -38
- data/lib/moped/bson/types.rb +0 -67
- data/lib/moped/logging.rb +0 -58
- data/lib/moped/session/context.rb +0 -115
- data/lib/moped/sockets/connectable.rb +0 -167
- data/lib/moped/sockets/ssl.rb +0 -50
- data/lib/moped/sockets/tcp.rb +0 -23
- data/lib/moped/threaded.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13a013a208ac0941e9a6d68d183574f2becafa79
|
4
|
+
data.tar.gz: 808d31b55227c47ff8d9503918c218d191b6b193
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56f954deab2f283830fc371a134d8f1b9055b6d985910886a27ed905a55b58403044f7acd9ea58e363b5dd296858a7dadc152ca8934e048c9fcec7ad60e5d600
|
7
|
+
data.tar.gz: b568935bcda3e6a73e5601819de389bab69f9e1acba1b40395bd0042b1a062ea86606e787778505fb08a3230855e9cf1b8be57d30925bd6611fe03967a8d1114
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,47 @@
|
|
1
1
|
# Overview
|
2
2
|
|
3
|
+
## 2.0.0
|
4
|
+
|
5
|
+
### New Features
|
6
|
+
|
7
|
+
* \#196 Adding method on collection to rename itself (Arthur Neves)
|
8
|
+
|
9
|
+
### API Changes (Backwards Incompatible)
|
10
|
+
|
11
|
+
* \#190 Connection retries are now logged. (Jan Paul Posma)
|
12
|
+
|
13
|
+
* \#133 Moped now supports the new read preferences that the core drivers
|
14
|
+
provide. These include:
|
15
|
+
|
16
|
+
- `:primary`: Will always read from a primary node. (default)
|
17
|
+
- `:primary_preferred`: Attempt a primary first, then secondary if none available.
|
18
|
+
- `:secondary`: Will always read from a secondary node.
|
19
|
+
- `:secondary_preferred`: Attempt a secondary first, then primary if none available.
|
20
|
+
- `:nearest`: Attempt to read from the node with the lowest latency.
|
21
|
+
|
22
|
+
Sample syntax:
|
23
|
+
|
24
|
+
Moped::Session.new([ "127.0.0.1:27017" ], read: :secondary)
|
25
|
+
session.with(read: :nearest)[:users].find
|
26
|
+
|
27
|
+
The `:consistency` option is no longer valid and will be ignored.
|
28
|
+
|
29
|
+
* \#92 Moped now defaults all writes to propagate (formerly "safe mode") and now
|
30
|
+
has different propagate semantics:
|
31
|
+
|
32
|
+
- `{ w: -1 }`: Don't verify writes and raise no network errors.
|
33
|
+
- `{ w: 0 }`: Don't verify writes and raise network errors.
|
34
|
+
- `{ w: 1 }`: Verify writes on the primary node. (default)
|
35
|
+
- `{ w: n }`: Verify writes on n number of nodes.
|
36
|
+
- `{ w: :majority }`: Verify writes on a majority of nodes.
|
37
|
+
|
38
|
+
Sample syntax:
|
39
|
+
|
40
|
+
Moped::Session.new([ "127.0.0.1:27017" ], write: { w: 0 })
|
41
|
+
session.with(write: { w: -1 })[:users].insert(document)
|
42
|
+
|
43
|
+
The `:safe` option is no longer valid and will be ignored.
|
44
|
+
|
3
45
|
## 1.5.1
|
4
46
|
|
5
47
|
### Resolved Issues
|
@@ -23,15 +65,10 @@
|
|
23
65
|
|
24
66
|
Moped::Session.new([ "127.0.0.1:27017" ], auto_discover: false)
|
25
67
|
|
26
|
-
* \#189 Moped now logs connection attempts during retries. (Jan Paul Posma)
|
27
|
-
|
28
68
|
## 1.4.6
|
29
69
|
|
30
70
|
### Resolved Issues
|
31
71
|
|
32
|
-
* \#192 Return the proper result after reauthentication attempts.
|
33
|
-
(Jonathan Hyman)
|
34
|
-
|
35
72
|
* \#191 Checking for "not authorized" in error messages. (Jonathan Hyman)
|
36
73
|
|
37
74
|
## 1.4.5
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
Moped [![Build Status](https://secure.travis-ci.org/mongoid/moped.png?branch=master&.png)](http://travis-ci.org/mongoid/moped) [![Code Climate](https://codeclimate.com/github/mongoid/moped.png)](https://codeclimate.com/github/mongoid/moped) [![Coverage Status](https://coveralls.io/repos/mongoid/moped/badge.png?branch=master)](https://coveralls.io/r/mongoid/moped?branch=master)
|
2
2
|
========
|
3
3
|
|
4
4
|
Moped is a MongoDB driver for Ruby, which exposes a simple, elegant, and fast
|
data/lib/moped.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require "logger"
|
2
3
|
require "stringio"
|
3
4
|
require "monitor"
|
4
|
-
|
5
|
-
require "
|
6
|
-
require "
|
7
|
-
require "moped/collection"
|
8
|
-
require "moped/connection"
|
9
|
-
require "moped/cursor"
|
10
|
-
require "moped/database"
|
5
|
+
require "timeout"
|
6
|
+
require "bson"
|
7
|
+
require "optionable"
|
11
8
|
require "moped/errors"
|
12
9
|
require "moped/indexes"
|
13
|
-
require "moped/
|
14
|
-
require "moped/
|
15
|
-
require "moped/node"
|
10
|
+
require "moped/loggable"
|
11
|
+
require "moped/uri"
|
16
12
|
require "moped/protocol"
|
17
|
-
require "moped/query"
|
18
13
|
require "moped/session"
|
19
|
-
require "moped/session/context"
|
20
|
-
require "moped/threaded"
|
21
14
|
require "moped/version"
|
15
|
+
|
16
|
+
module Moped
|
17
|
+
extend Loggable
|
18
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Moped
|
3
|
+
|
4
|
+
# Encapsulates behaviour around addresses and resolving dns.
|
5
|
+
#
|
6
|
+
# @since 2.0.0
|
7
|
+
class Address
|
8
|
+
|
9
|
+
# @!attribute host
|
10
|
+
# @return [ String ] The host name.
|
11
|
+
# @!attribute ip
|
12
|
+
# @return [ String ] The ip address.
|
13
|
+
# @!attribute original
|
14
|
+
# @return [ String ] The original host name.
|
15
|
+
# @!attribute port
|
16
|
+
# @return [ Integer ] The port.
|
17
|
+
# @!attribute resolved
|
18
|
+
# @return [ String ] The full resolved address.
|
19
|
+
attr_reader :host, :ip, :original, :port, :resolved
|
20
|
+
|
21
|
+
# Instantiate the new address.
|
22
|
+
#
|
23
|
+
# @example Instantiate the address.
|
24
|
+
# Moped::Address.new("localhost:27017")
|
25
|
+
#
|
26
|
+
# @param [ String ] address The host:port pair as a string.
|
27
|
+
#
|
28
|
+
# @since 2.0.0
|
29
|
+
def initialize(address)
|
30
|
+
@original = address
|
31
|
+
@host, port = address.split(":")
|
32
|
+
@port = (port || 27017).to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
# Resolve the address for the provided node. If the address cannot be
|
36
|
+
# resolved the node will be flagged as down.
|
37
|
+
#
|
38
|
+
# @example Resolve the address.
|
39
|
+
# address.resolve(node)
|
40
|
+
#
|
41
|
+
# @param [ Node ] node The node to resolve for.
|
42
|
+
#
|
43
|
+
# @return [ String ] The resolved address.
|
44
|
+
#
|
45
|
+
# @since 2.0.0
|
46
|
+
def resolve(node)
|
47
|
+
begin
|
48
|
+
@ip ||= Socket.getaddrinfo(host, nil, Socket::AF_INET, Socket::SOCK_STREAM).first[3]
|
49
|
+
@resolved ||= "#{ip}:#{port}"
|
50
|
+
rescue SocketError => e
|
51
|
+
node.instrument(Node::WARN, prefix: " MOPED:", message: "Could not resolve IP for: #{original}")
|
52
|
+
node.down! and false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Moped
|
3
|
+
|
4
|
+
# Provides behaviour to nodes around authentication.
|
5
|
+
#
|
6
|
+
# @since 2.0.0
|
7
|
+
module Authenticatable
|
8
|
+
|
9
|
+
# Apply authentication credentials.
|
10
|
+
#
|
11
|
+
# @example Apply the authentication credentials.
|
12
|
+
# node.apply_credentials({ "moped_test" => [ "user", "pass" ]})
|
13
|
+
#
|
14
|
+
# @param [ Hash ] credentials The authentication credentials in the form:
|
15
|
+
# { database_name: [ user, password ]}
|
16
|
+
#
|
17
|
+
# @return [ Object ] The authenticated object.
|
18
|
+
#
|
19
|
+
# @since 2.0.0
|
20
|
+
def apply_credentials(logins)
|
21
|
+
unless credentials == logins
|
22
|
+
logouts = credentials.keys - logins.keys
|
23
|
+
logouts.each do |database|
|
24
|
+
logout(database)
|
25
|
+
end
|
26
|
+
logins.each do |database, (username, password)|
|
27
|
+
unless credentials[database] == [ username, password ]
|
28
|
+
login(database, username, password)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get the applied credentials.
|
36
|
+
#
|
37
|
+
# @example Get the applied credentials.
|
38
|
+
# node.credentials
|
39
|
+
#
|
40
|
+
# @return [ Hash ] The credentials.
|
41
|
+
#
|
42
|
+
# @since 2.0.0
|
43
|
+
def credentials
|
44
|
+
@credentials ||= {}
|
45
|
+
end
|
46
|
+
|
47
|
+
# Login the user to the provided database with the supplied password.
|
48
|
+
#
|
49
|
+
# @example Login the user to the database.
|
50
|
+
# node.login("moped_test", "user", "pass")
|
51
|
+
#
|
52
|
+
# @param [ String ] database The database name.
|
53
|
+
# @param [ String ] username The username.
|
54
|
+
# @param [ String ] password The password.
|
55
|
+
#
|
56
|
+
# @raise [ Errors::AuthenticationFailure ] If the login failed.
|
57
|
+
#
|
58
|
+
# @return [ Array ] The username and password.
|
59
|
+
#
|
60
|
+
# @since 2.0.0
|
61
|
+
def login(database, username, password)
|
62
|
+
getnonce = Protocol::Command.new(database, getnonce: 1)
|
63
|
+
result = Operation::Read.new(getnonce).execute(self)
|
64
|
+
authenticate = Protocol::Commands::Authenticate.new(database, username, password, result["nonce"])
|
65
|
+
connection do |conn|
|
66
|
+
conn.write([ authenticate ])
|
67
|
+
document = conn.read.documents.first
|
68
|
+
raise Errors::AuthenticationFailure.new(authenticate, document) unless document["ok"] == 1
|
69
|
+
credentials[database] = [username, password]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Logout the user from the provided database.
|
74
|
+
#
|
75
|
+
# @example Logout from the provided database.
|
76
|
+
# node.logout("moped_test")
|
77
|
+
#
|
78
|
+
# @param [ String ] database The database name.
|
79
|
+
#
|
80
|
+
# @return [ Array ] The username and password.
|
81
|
+
#
|
82
|
+
# @since 2.0.0
|
83
|
+
def logout(database)
|
84
|
+
command = Protocol::Command.new(database, logout: 1)
|
85
|
+
Operation::Read.new(command).execute(self)
|
86
|
+
credentials.delete(database)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/moped/cluster.rb
CHANGED
@@ -1,23 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "moped/node"
|
3
|
+
|
1
4
|
module Moped
|
2
5
|
|
3
6
|
# The cluster represents a cluster of MongoDB server nodes, either a single
|
4
7
|
# node, a replica set, or a mongos server.
|
8
|
+
#
|
9
|
+
# @since 1.0.0
|
5
10
|
class Cluster
|
6
11
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
12
|
+
# The default interval that a node would be flagged as "down".
|
13
|
+
#
|
14
|
+
# @since 2.0.0
|
15
|
+
DOWN_INTERVAL = 30
|
16
|
+
|
17
|
+
# The default interval that a node should be refreshed in.
|
18
|
+
#
|
19
|
+
# @since 2.0.0
|
20
|
+
REFRESH_INTERVAL = 300
|
21
|
+
|
22
|
+
# The default time to wait to retry an operation.
|
23
|
+
#
|
24
|
+
# @since 2.0.0
|
25
|
+
RETRY_INTERVAL = 0.25
|
26
|
+
|
27
|
+
# @!attribute options
|
28
|
+
# @return [ Hash ] The refresh options.
|
29
|
+
# @!attribute peers
|
30
|
+
# @return [ Array<Node> ] The node peers.
|
31
|
+
# @!attribute seeds
|
32
|
+
# @return [ Array<Node> ] The seed nodes.
|
33
|
+
attr_reader :options, :peers, :seeds
|
10
34
|
|
11
35
|
# Get the credentials for the cluster.
|
12
36
|
#
|
13
|
-
# @example Get the
|
14
|
-
#
|
37
|
+
# @example Get the applied credentials.
|
38
|
+
# node.credentials
|
15
39
|
#
|
16
|
-
# @return [ Hash ]
|
40
|
+
# @return [ Hash ] The credentials.
|
17
41
|
#
|
18
|
-
# @since
|
19
|
-
def
|
20
|
-
@
|
42
|
+
# @since 2.0.0
|
43
|
+
def credentials
|
44
|
+
@credentials ||= {}
|
21
45
|
end
|
22
46
|
|
23
47
|
# Disconnects all nodes in the cluster. This should only be used in cases
|
@@ -28,7 +52,7 @@ module Moped
|
|
28
52
|
#
|
29
53
|
# @since 1.2.0
|
30
54
|
def disconnect
|
31
|
-
nodes
|
55
|
+
nodes.each { |node| node.disconnect } and true
|
32
56
|
end
|
33
57
|
|
34
58
|
# Get the interval at which a node should be flagged as down before
|
@@ -41,45 +65,7 @@ module Moped
|
|
41
65
|
#
|
42
66
|
# @since 1.2.7
|
43
67
|
def down_interval
|
44
|
-
options[:down_interval]
|
45
|
-
end
|
46
|
-
|
47
|
-
# Get the number of times an operation should be retried before raising an
|
48
|
-
# error.
|
49
|
-
#
|
50
|
-
# @example Get the maximum retries.
|
51
|
-
# cluster.max_retries
|
52
|
-
#
|
53
|
-
# @return [ Integer ] The max retries.
|
54
|
-
#
|
55
|
-
# @since 1.2.7
|
56
|
-
def max_retries
|
57
|
-
options[:max_retries]
|
58
|
-
end
|
59
|
-
|
60
|
-
# Get the interval in which the node list should be refreshed.
|
61
|
-
#
|
62
|
-
# @example Get the refresh interval, in seconds.
|
63
|
-
# cluster.refresh_interval
|
64
|
-
#
|
65
|
-
# @return [ Integer ] The refresh interval.
|
66
|
-
#
|
67
|
-
# @since 1.2.7
|
68
|
-
def refresh_interval
|
69
|
-
options[:refresh_interval]
|
70
|
-
end
|
71
|
-
|
72
|
-
# Get the operation retry interval - the time to wait before retrying a
|
73
|
-
# single operation.
|
74
|
-
#
|
75
|
-
# @example Get the retry interval, in seconds.
|
76
|
-
# cluster.retry_interval
|
77
|
-
#
|
78
|
-
# @return [ Integer ] The retry interval.
|
79
|
-
#
|
80
|
-
# @since 1.2.7
|
81
|
-
def retry_interval
|
82
|
-
options[:retry_interval]
|
68
|
+
@down_interval ||= options[:down_interval] || DOWN_INTERVAL
|
83
69
|
end
|
84
70
|
|
85
71
|
# Initialize the new cluster.
|
@@ -98,16 +84,34 @@ module Moped
|
|
98
84
|
#
|
99
85
|
# @since 1.0.0
|
100
86
|
def initialize(hosts, options)
|
101
|
-
@seeds = hosts
|
102
|
-
@nodes = hosts.map { |host| Node.new(host, options) }
|
87
|
+
@seeds = hosts.map{ |host| Node.new(host, options) }
|
103
88
|
@peers = []
|
89
|
+
@options = options
|
90
|
+
end
|
91
|
+
|
92
|
+
# Provide a pretty string for cluster inspection.
|
93
|
+
#
|
94
|
+
# @example Inspect the cluster.
|
95
|
+
# cluster.inspect
|
96
|
+
#
|
97
|
+
# @return [ String ] A nicely formatted string.
|
98
|
+
#
|
99
|
+
# @since 1.0.0
|
100
|
+
def inspect
|
101
|
+
"#<#{self.class.name}:#{object_id} @seeds=#{seeds.inspect}>"
|
102
|
+
end
|
104
103
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
104
|
+
# Get the number of times an operation should be retried before raising an
|
105
|
+
# error.
|
106
|
+
#
|
107
|
+
# @example Get the maximum retries.
|
108
|
+
# cluster.max_retries
|
109
|
+
#
|
110
|
+
# @return [ Integer ] The max retries.
|
111
|
+
#
|
112
|
+
# @since 1.2.7
|
113
|
+
def max_retries
|
114
|
+
@max_retries ||= options[:max_retries] || seeds.size
|
111
115
|
end
|
112
116
|
|
113
117
|
# Returns the list of available nodes, refreshing 1) any nodes which were
|
@@ -120,25 +124,19 @@ module Moped
|
|
120
124
|
# @return [ Array<Node> ] the list of available nodes.
|
121
125
|
#
|
122
126
|
# @since 1.0.0
|
123
|
-
def nodes
|
124
|
-
current_time = Time.new
|
125
|
-
down_boundary = current_time - down_interval
|
126
|
-
refresh_boundary = current_time - refresh_interval
|
127
|
-
|
127
|
+
def nodes
|
128
128
|
# Find the nodes that were down but are ready to be refreshed, or those
|
129
129
|
# with stale connection information.
|
130
|
-
needs_refresh, available =
|
131
|
-
|
130
|
+
needs_refresh, available = seeds.partition do |node|
|
131
|
+
refreshable?(node)
|
132
132
|
end
|
133
133
|
|
134
134
|
# Refresh those nodes.
|
135
|
-
available.concat
|
135
|
+
available.concat(refresh(needs_refresh))
|
136
136
|
|
137
137
|
# Now return all the nodes that are available and participating in the
|
138
138
|
# replica set.
|
139
|
-
available.reject
|
140
|
-
node.down? || !member?(node) || (!opts[:include_arbiters] && node.arbiter?)
|
141
|
-
end
|
139
|
+
available.reject{ |node| node.down? }
|
142
140
|
end
|
143
141
|
|
144
142
|
# Refreshes information for each of the nodes provided. The node list
|
@@ -155,24 +153,19 @@ module Moped
|
|
155
153
|
# @return [ Array<Node> ] the available nodes
|
156
154
|
#
|
157
155
|
# @since 1.0.0
|
158
|
-
def refresh(nodes_to_refresh =
|
156
|
+
def refresh(nodes_to_refresh = seeds)
|
159
157
|
refreshed_nodes = []
|
160
158
|
seen = {}
|
161
|
-
|
162
159
|
# Set up a recursive lambda function for refreshing a node and it's peers.
|
163
160
|
refresh_node = ->(node) do
|
164
161
|
unless seen[node]
|
165
162
|
seen[node] = true
|
166
|
-
|
167
163
|
# Add the node to the global list of known nodes.
|
168
|
-
|
169
|
-
|
164
|
+
seeds.push(node) unless seeds.include?(node)
|
170
165
|
begin
|
171
166
|
node.refresh
|
172
|
-
|
173
167
|
# This node is good, so add it to the list of nodes to return.
|
174
|
-
refreshed_nodes
|
175
|
-
|
168
|
+
refreshed_nodes.push(node) unless refreshed_nodes.include?(node)
|
176
169
|
# Now refresh any newly discovered peer nodes - this will also
|
177
170
|
# remove nodes that are not included in the peer list.
|
178
171
|
refresh_peers(node, &refresh_node)
|
@@ -183,7 +176,32 @@ module Moped
|
|
183
176
|
end
|
184
177
|
|
185
178
|
nodes_to_refresh.each(&refresh_node)
|
186
|
-
refreshed_nodes
|
179
|
+
refreshed_nodes
|
180
|
+
end
|
181
|
+
|
182
|
+
# Get the interval in which the node list should be refreshed.
|
183
|
+
#
|
184
|
+
# @example Get the refresh interval, in seconds.
|
185
|
+
# cluster.refresh_interval
|
186
|
+
#
|
187
|
+
# @return [ Integer ] The refresh interval.
|
188
|
+
#
|
189
|
+
# @since 1.2.7
|
190
|
+
def refresh_interval
|
191
|
+
@refresh_interval ||= options[:refresh_interval] || REFRESH_INTERVAL
|
192
|
+
end
|
193
|
+
|
194
|
+
# Get the operation retry interval - the time to wait before retrying a
|
195
|
+
# single operation.
|
196
|
+
#
|
197
|
+
# @example Get the retry interval, in seconds.
|
198
|
+
# cluster.retry_interval
|
199
|
+
#
|
200
|
+
# @return [ Integer ] The retry interval.
|
201
|
+
#
|
202
|
+
# @since 1.2.7
|
203
|
+
def retry_interval
|
204
|
+
@retry_interval ||= options[:retry_interval] || RETRY_INTERVAL
|
187
205
|
end
|
188
206
|
|
189
207
|
# Yields the replica set's primary node to the provided block. This method
|
@@ -202,30 +220,16 @@ module Moped
|
|
202
220
|
# @return [ Object ] The result of the yield.
|
203
221
|
#
|
204
222
|
# @since 1.0.0
|
205
|
-
def with_primary(
|
223
|
+
def with_primary(&block)
|
206
224
|
if node = nodes.find(&:primary?)
|
207
225
|
begin
|
208
226
|
node.ensure_primary do
|
209
|
-
return yield
|
227
|
+
return yield(node.apply_credentials(credentials))
|
210
228
|
end
|
211
229
|
rescue Errors::ConnectionFailure, Errors::ReplicaSetReconfigured
|
212
|
-
# Fall through to the code below if our connection was dropped or the
|
213
|
-
# node is no longer the primary.
|
214
230
|
end
|
215
231
|
end
|
216
|
-
|
217
|
-
if retries > 0
|
218
|
-
# We couldn't find a primary node, so refresh the list and try again.
|
219
|
-
warning(" MOPED: Retrying connection to primary for replica set #{inspect}")
|
220
|
-
sleep(retry_interval)
|
221
|
-
refresh
|
222
|
-
with_primary(retries - 1, &block)
|
223
|
-
else
|
224
|
-
raise(
|
225
|
-
Errors::ConnectionFailure,
|
226
|
-
"Could not connect to a primary node for replica set #{inspect}"
|
227
|
-
)
|
228
|
-
end
|
232
|
+
raise Errors::ConnectionFailure, "Could not connect to a primary node for replica set #{inspect}"
|
229
233
|
end
|
230
234
|
|
231
235
|
# Yields a secondary node if available, otherwise the primary node. This
|
@@ -243,63 +247,92 @@ module Moped
|
|
243
247
|
# @return [ Object ] The result of the yield.
|
244
248
|
#
|
245
249
|
# @since 1.0.0
|
246
|
-
def with_secondary(
|
247
|
-
available_nodes = nodes.
|
248
|
-
|
250
|
+
def with_secondary(&block)
|
251
|
+
available_nodes = nodes.select(&:secondary?).shuffle!
|
249
252
|
while node = available_nodes.shift
|
250
253
|
begin
|
251
|
-
return yield
|
252
|
-
rescue Errors::ConnectionFailure
|
253
|
-
warning(" MOPED: Connection failed to secondary node #{node.inspect}, trying next node.")
|
254
|
-
# That node's no good, so let's try the next one.
|
255
|
-
next
|
256
|
-
rescue Errors::ReplicaSetReconfigured
|
257
|
-
# That node's no good, so let's try the next one.
|
254
|
+
return yield(node.apply_credentials(credentials))
|
255
|
+
rescue Errors::ConnectionFailure => e
|
258
256
|
next
|
259
257
|
end
|
260
258
|
end
|
261
|
-
|
262
|
-
if retries > 0
|
263
|
-
# We couldn't find a secondary or primary node, so refresh the list and
|
264
|
-
# try again.
|
265
|
-
warning(" MOPED: Could not connect to any node in replica set #{inspect}, refreshing list.")
|
266
|
-
sleep(retry_interval)
|
267
|
-
refresh
|
268
|
-
with_secondary(retries - 1, &block)
|
269
|
-
else
|
270
|
-
raise(
|
271
|
-
Errors::ConnectionFailure,
|
272
|
-
"Could not connect to any secondary or primary nodes for replica set #{inspect}"
|
273
|
-
)
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def inspect
|
278
|
-
"<#{self.class.name} nodes=#{@nodes.inspect}>"
|
259
|
+
raise Errors::ConnectionFailure, "Could not connect to a secondary node for replica set #{inspect}"
|
279
260
|
end
|
280
261
|
|
281
262
|
private
|
282
263
|
|
283
|
-
|
284
|
-
|
264
|
+
# Get the boundary where a node that is down would need to be refreshed.
|
265
|
+
#
|
266
|
+
# @api private
|
267
|
+
#
|
268
|
+
# @example Get the down boundary.
|
269
|
+
# cluster.down_boundary
|
270
|
+
#
|
271
|
+
# @return [ Time ] The down boundary.
|
272
|
+
#
|
273
|
+
# @since 2.0.0
|
274
|
+
def down_boundary
|
275
|
+
Time.new - down_interval
|
285
276
|
end
|
286
277
|
|
287
|
-
|
288
|
-
|
278
|
+
# Get the standard refresh boundary to discover new nodes.
|
279
|
+
#
|
280
|
+
# @api private
|
281
|
+
#
|
282
|
+
# @example Get the refresh boundary.
|
283
|
+
# cluster.refresh_boundary
|
284
|
+
#
|
285
|
+
# @return [ Time ] The refresh boundary.
|
286
|
+
#
|
287
|
+
# @since 2.0.0
|
288
|
+
def refresh_boundary
|
289
|
+
Time.new - refresh_interval
|
289
290
|
end
|
290
291
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
292
|
+
# Is the provided node refreshable? This is in the case where the refresh
|
293
|
+
# boundary has passed, or the node has been down longer than the down
|
294
|
+
# boundary.
|
295
|
+
#
|
296
|
+
# @api private
|
297
|
+
#
|
298
|
+
# @example Is the node refreshable?
|
299
|
+
# cluster.refreshable?(node)
|
300
|
+
#
|
301
|
+
# @param [ Node ] node The Node to check.
|
302
|
+
#
|
303
|
+
# @since 2.0.0
|
304
|
+
def refreshable?(node)
|
305
|
+
node.down? ? node.down_at < down_boundary : node.needs_refresh?(refresh_boundary)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Creating a cloned cluster requires cloning all the seed nodes.
|
309
|
+
#
|
310
|
+
# @api prviate
|
311
|
+
#
|
312
|
+
# @example Clone the cluster.
|
313
|
+
# cluster.clone
|
314
|
+
#
|
315
|
+
# @return [ Cluster ] The cloned cluster.
|
316
|
+
#
|
317
|
+
# @since 1.0.0
|
318
|
+
def initialize_copy(_)
|
319
|
+
@seeds = seeds.map(&:dup)
|
298
320
|
end
|
299
321
|
|
300
|
-
|
301
|
-
|
302
|
-
|
322
|
+
# Refresh the peers based on the node's peers.
|
323
|
+
#
|
324
|
+
# @api private
|
325
|
+
#
|
326
|
+
# @example Refresh the peers.
|
327
|
+
# cluster.refresh_peers(node)
|
328
|
+
#
|
329
|
+
# @param [ Node ] node The node to refresh the peers for.
|
330
|
+
#
|
331
|
+
# @since 1.0.0
|
332
|
+
def refresh_peers(node, &block)
|
333
|
+
node.peers.each do |node|
|
334
|
+
block.call(node) unless seeds.include?(node)
|
335
|
+
peers.push(node) unless peers.include?(node)
|
303
336
|
end
|
304
337
|
end
|
305
338
|
end
|