mongo 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/csasl/csasl.bundle +0 -0
- data/lib/mongo/client.rb +6 -2
- data/lib/mongo/cluster.rb +36 -0
- data/lib/mongo/collection/view/readable.rb +1 -1
- data/lib/mongo/error/operation_failure.rb +32 -1
- data/lib/mongo/retryable.rb +17 -1
- data/lib/mongo/version.rb +1 -1
- data/spec/mongo/client_spec.rb +20 -0
- data/spec/mongo/collection/view/readable_spec.rb +4 -0
- data/spec/mongo/retryable_spec.rb +80 -6
- metadata +5 -26
- checksums.yaml.gz.sig +0 -5
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8c7fcad401a8586ae8ba1c0b864238fce8039a2
|
4
|
+
data.tar.gz: 9499b901d192abf1910f71a47fa0316633c32c31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b4532f3365fda5b9351e334a882e92ccaa7fb0c006fa84b3e5e0bb922f9a8b3a5a7366f00ad1b505d0d7d4298c5438b5e57a5ce0f397105c8f49835618681b3
|
7
|
+
data.tar.gz: 262cb8675d073741690971aa9e141fb53324de2a3835f6e0e024b8faa654fba1aa3c451b4711793ef1e7df0d039e765675c5cb4bf1d1229a214ab70389dac379
|
Binary file
|
data/lib/mongo/client.rb
CHANGED
@@ -36,8 +36,8 @@ module Mongo
|
|
36
36
|
# @return [ Hash ] options The configuration options.
|
37
37
|
attr_reader :options
|
38
38
|
|
39
|
-
# Delegate command execution to the current database.
|
40
|
-
def_delegators :@database, :command
|
39
|
+
# Delegate command and collections execution to the current database.
|
40
|
+
def_delegators :@database, :command, :collections
|
41
41
|
|
42
42
|
# Delegate subscription to monitoring.
|
43
43
|
def_delegators :@monitoring, :subscribe, :unsubscribe
|
@@ -151,6 +151,10 @@ module Mongo
|
|
151
151
|
# @option options [ Logger ] :logger A custom logger if desired.
|
152
152
|
# @option options [ true, false ] :truncate_logs Whether to truncate the
|
153
153
|
# logs at the default 250 characters.
|
154
|
+
# @option options [ Integer ] :max_read_retries The maximum number of read
|
155
|
+
# retries on mongos query failures.
|
156
|
+
# @option options [ Float ] :read_retry_interval The interval, in seconds,
|
157
|
+
# in which reads on a mongos are retried.
|
154
158
|
#
|
155
159
|
# @since 2.0.0
|
156
160
|
def initialize(addresses_or_uri, options = Options::Redacted.new)
|
data/lib/mongo/cluster.rb
CHANGED
@@ -25,6 +25,16 @@ module Mongo
|
|
25
25
|
include Event::Subscriber
|
26
26
|
include Loggable
|
27
27
|
|
28
|
+
# The default number of mongos read retries.
|
29
|
+
#
|
30
|
+
# @since 2.1.1
|
31
|
+
MAX_READ_RETRIES = 1
|
32
|
+
|
33
|
+
# The default mongos read retry interval, in seconds.
|
34
|
+
#
|
35
|
+
# @since 2.1.1
|
36
|
+
READ_RETRY_INTERVAL = 5
|
37
|
+
|
28
38
|
# @return [ Hash ] The options hash.
|
29
39
|
attr_reader :options
|
30
40
|
|
@@ -143,6 +153,32 @@ module Mongo
|
|
143
153
|
@topology = topology.elect_primary(description, servers_list)
|
144
154
|
end
|
145
155
|
|
156
|
+
# Get the maximum number of times the cluster can retry a read operation on
|
157
|
+
# a mongos.
|
158
|
+
#
|
159
|
+
# @example Get the max read retries.
|
160
|
+
# cluster.max_read_retries
|
161
|
+
#
|
162
|
+
# @return [ Integer ] The maximum retries.
|
163
|
+
#
|
164
|
+
# @since 2.1.1
|
165
|
+
def max_read_retries
|
166
|
+
options[:max_read_retries] || MAX_READ_RETRIES
|
167
|
+
end
|
168
|
+
|
169
|
+
# Get the interval, in seconds, in which a mongos read operation is
|
170
|
+
# retried.
|
171
|
+
#
|
172
|
+
# @example Get the read retry interval.
|
173
|
+
# cluster.read_retry_interval
|
174
|
+
#
|
175
|
+
# @return [ Float ] The interval.
|
176
|
+
#
|
177
|
+
# @since 2.1.1
|
178
|
+
def read_retry_interval
|
179
|
+
options[:read_retry_interval] || READ_RETRY_INTERVAL
|
180
|
+
end
|
181
|
+
|
146
182
|
# Notify the cluster that a standalone server was discovered so that the
|
147
183
|
# topology can be updated accordingly.
|
148
184
|
#
|
@@ -138,7 +138,7 @@ module Mongo
|
|
138
138
|
cmd[:limit] = options[:limit] if options[:limit]
|
139
139
|
cmd[:maxTimeMS] = options[:max_time_ms] if options[:max_time_ms]
|
140
140
|
read_with_retry do
|
141
|
-
database.command(cmd, options).n
|
141
|
+
database.command(cmd, options).n.to_i
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
@@ -18,6 +18,37 @@ module Mongo
|
|
18
18
|
# Raised when an operation fails for some reason.
|
19
19
|
#
|
20
20
|
# @since 2.0.0
|
21
|
-
class OperationFailure < Error
|
21
|
+
class OperationFailure < Error
|
22
|
+
|
23
|
+
# These are magic error messages that could indicate a cluster
|
24
|
+
# reconfiguration behind a mongos. We cannot check error codes as they
|
25
|
+
# change between versions, for example 15988 which has 2 completely
|
26
|
+
# different meanings between 2.4 and 3.0.
|
27
|
+
#
|
28
|
+
# @since 2.1.1
|
29
|
+
RETRY_MESSAGES = [
|
30
|
+
'transport error',
|
31
|
+
'socket exception',
|
32
|
+
"can't connect",
|
33
|
+
'no master',
|
34
|
+
'not master',
|
35
|
+
'connect failed',
|
36
|
+
'error querying',
|
37
|
+
'could not get last error',
|
38
|
+
'connection attempt failed'
|
39
|
+
].freeze
|
40
|
+
|
41
|
+
# Can the operation that caused the error be retried?
|
42
|
+
#
|
43
|
+
# @example Is the error retryable?
|
44
|
+
# error.retryable?
|
45
|
+
#
|
46
|
+
# @return [ true, false ] If the error is retryable.
|
47
|
+
#
|
48
|
+
# @since 2.1.1
|
49
|
+
def retryable?
|
50
|
+
RETRY_MESSAGES.any?{ |m| message.include?(m) }
|
51
|
+
end
|
52
|
+
end
|
22
53
|
end
|
23
54
|
end
|
data/lib/mongo/retryable.rb
CHANGED
@@ -26,6 +26,8 @@ module Mongo
|
|
26
26
|
|
27
27
|
# Execute a read operation with a retry.
|
28
28
|
#
|
29
|
+
# @api private
|
30
|
+
#
|
29
31
|
# @example Execute the read.
|
30
32
|
# read_with_retry do
|
31
33
|
# ...
|
@@ -33,21 +35,35 @@ module Mongo
|
|
33
35
|
#
|
34
36
|
# @note This only retries read operations on socket errors.
|
35
37
|
#
|
38
|
+
# @param [ Integer ] attempt The retry attempt count - for internal use.
|
36
39
|
# @param [ Proc ] block The block to execute.
|
37
40
|
#
|
38
41
|
# @return [ Result ] The result of the operation.
|
39
42
|
#
|
40
43
|
# @since 2.1.0
|
41
|
-
def read_with_retry(&block)
|
44
|
+
def read_with_retry(attempt = 0, &block)
|
42
45
|
begin
|
43
46
|
block.call
|
44
47
|
rescue Error::SocketError, Error::SocketTimeoutError
|
45
48
|
retry_operation(&block)
|
49
|
+
rescue Error::OperationFailure => e
|
50
|
+
if cluster.sharded? && e.retryable?
|
51
|
+
if attempt < cluster.max_read_retries
|
52
|
+
# We don't scan the cluster in this case as Mongos always returns
|
53
|
+
# ready after a ping no matter what the state behind it is.
|
54
|
+
sleep(cluster.read_retry_interval)
|
55
|
+
read_with_retry(attempt - 1, &block)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
raise e
|
59
|
+
end
|
46
60
|
end
|
47
61
|
end
|
48
62
|
|
49
63
|
# Execute a write operation with a retry.
|
50
64
|
#
|
65
|
+
# @api private
|
66
|
+
#
|
51
67
|
# @example Execute the write.
|
52
68
|
# write_with_retry do
|
53
69
|
# ...
|
data/lib/mongo/version.rb
CHANGED
data/spec/mongo/client_spec.rb
CHANGED
@@ -742,4 +742,24 @@ describe Mongo::Client do
|
|
742
742
|
expect(client.dup.options).to be_a(Mongo::Options::Redacted)
|
743
743
|
end
|
744
744
|
end
|
745
|
+
|
746
|
+
describe '#collections' do
|
747
|
+
|
748
|
+
before do
|
749
|
+
authorized_client.database[:users].create
|
750
|
+
end
|
751
|
+
|
752
|
+
after do
|
753
|
+
authorized_client.database[:users].drop
|
754
|
+
end
|
755
|
+
|
756
|
+
let(:collection) do
|
757
|
+
Mongo::Collection.new(authorized_client.database, 'users')
|
758
|
+
end
|
759
|
+
|
760
|
+
it 'refers the current database collections' do
|
761
|
+
expect(authorized_client.collections).to include(collection)
|
762
|
+
expect(authorized_client.collections).to all(be_a(Mongo::Collection))
|
763
|
+
end
|
764
|
+
end
|
745
765
|
end
|
@@ -227,6 +227,10 @@ describe Mongo::Collection::View::Readable do
|
|
227
227
|
it 'returns the count of matching documents' do
|
228
228
|
expect(view.count).to eq(1)
|
229
229
|
end
|
230
|
+
|
231
|
+
it 'returns an integer' do
|
232
|
+
expect(view.count).to be_a(Integer)
|
233
|
+
end
|
230
234
|
end
|
231
235
|
|
232
236
|
context 'when no selector is provided' do
|
@@ -14,6 +14,14 @@ describe Mongo::Retryable do
|
|
14
14
|
@cluster = cluster
|
15
15
|
end
|
16
16
|
|
17
|
+
def max_read_retries
|
18
|
+
cluster.max_read_retries
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_retry_interval
|
22
|
+
cluster.read_retry_interval
|
23
|
+
end
|
24
|
+
|
17
25
|
def read
|
18
26
|
read_with_retry do
|
19
27
|
operation.execute
|
@@ -81,14 +89,80 @@ describe Mongo::Retryable do
|
|
81
89
|
|
82
90
|
context 'when an operation failure occurs' do
|
83
91
|
|
84
|
-
|
85
|
-
|
92
|
+
context 'when the cluster is not a mongos' do
|
93
|
+
|
94
|
+
before do
|
95
|
+
expect(operation).to receive(:execute).and_raise(Mongo::Error::OperationFailure).ordered
|
96
|
+
expect(cluster).to receive(:sharded?).and_return(false)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'raises an exception' do
|
100
|
+
expect {
|
101
|
+
retryable.read
|
102
|
+
}.to raise_error(Mongo::Error::OperationFailure)
|
103
|
+
end
|
86
104
|
end
|
87
105
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
106
|
+
context 'when the cluster is a mongos' do
|
107
|
+
|
108
|
+
context 'when the operation failure is not retryable' do
|
109
|
+
|
110
|
+
let(:error) do
|
111
|
+
Mongo::Error::OperationFailure.new('not authorized')
|
112
|
+
end
|
113
|
+
|
114
|
+
before do
|
115
|
+
expect(operation).to receive(:execute).and_raise(error).ordered
|
116
|
+
expect(cluster).to receive(:sharded?).and_return(true)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'raises the exception' do
|
120
|
+
expect {
|
121
|
+
retryable.read
|
122
|
+
}.to raise_error(Mongo::Error::OperationFailure)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'when the operation failure is retryable' do
|
127
|
+
|
128
|
+
let(:error) do
|
129
|
+
Mongo::Error::OperationFailure.new('no master')
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when the retry succeeds' do
|
133
|
+
|
134
|
+
before do
|
135
|
+
expect(operation).to receive(:execute).and_raise(error).ordered
|
136
|
+
expect(cluster).to receive(:sharded?).and_return(true)
|
137
|
+
expect(cluster).to receive(:max_read_retries).and_return(1).ordered
|
138
|
+
expect(cluster).to receive(:read_retry_interval).and_return(0.1).ordered
|
139
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'returns the result' do
|
143
|
+
expect(retryable.read).to be true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'when the retry fails once and then succeeds' do
|
148
|
+
|
149
|
+
before do
|
150
|
+
expect(operation).to receive(:execute).and_raise(error).ordered
|
151
|
+
expect(cluster).to receive(:sharded?).and_return(true)
|
152
|
+
expect(cluster).to receive(:max_read_retries).and_return(1).ordered
|
153
|
+
expect(cluster).to receive(:read_retry_interval).and_return(0.1).ordered
|
154
|
+
expect(operation).to receive(:execute).and_raise(error).ordered
|
155
|
+
expect(cluster).to receive(:sharded?).and_return(true)
|
156
|
+
expect(cluster).to receive(:max_read_retries).and_return(1).ordered
|
157
|
+
expect(cluster).to receive(:read_retry_interval).and_return(0.1).ordered
|
158
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'returns the result' do
|
162
|
+
expect(retryable.read).to be true
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
92
166
|
end
|
93
167
|
end
|
94
168
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Brock
|
@@ -9,30 +9,8 @@ authors:
|
|
9
9
|
- Durran Jordan
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
|
-
cert_chain:
|
13
|
-
-
|
14
|
-
-----BEGIN CERTIFICATE-----
|
15
|
-
MIIDfDCCAmSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBCMRQwEgYDVQQDDAtkcml2
|
16
|
-
ZXItcnVieTEVMBMGCgmSJomT8ixkARkWBTEwZ2VuMRMwEQYKCZImiZPyLGQBGRYD
|
17
|
-
Y29tMB4XDTE0MTEyMDE1NTYxOVoXDTE1MTEyMDE1NTYxOVowQjEUMBIGA1UEAwwL
|
18
|
-
ZHJpdmVyLXJ1YnkxFTATBgoJkiaJk/IsZAEZFgUxMGdlbjETMBEGCgmSJomT8ixk
|
19
|
-
ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFdSAa8fRm1
|
20
|
-
bAM9za6Z0fAH4g02bqM1NGnw8zJQrE/PFrFfY6IFCT2AsLfOwr1maVm7iU1+kdVI
|
21
|
-
IQ+iI/9+E+ArJ+rbGV3dDPQ+SLl3mLT+vXjfjcxMqI2IW6UuVtt2U3Rxd4QU0kdT
|
22
|
-
JxmcPYs5fDN6BgYc6XXgUjy3m+Kwha2pGctdciUOwEfOZ4RmNRlEZKCMLRHdFP8j
|
23
|
-
4WTnJSGfXDiuoXICJb5yOPOZPuaapPSNXp93QkUdsqdKC32I+KMpKKYGBQ6yisfA
|
24
|
-
5MyVPPCzLR1lP5qXVGJPnOqUAkvEUfCahg7EP9tI20qxiXrR6TSEraYhIFXL0EGY
|
25
|
-
u8KAcPHm5KkCAwEAAaN9MHswCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
|
26
|
-
BBYEFFt3WbF+9JpUjAoj62cQBgNb8HzXMCAGA1UdEQQZMBeBFWRyaXZlci1ydWJ5
|
27
|
-
QDEwZ2VuLmNvbTAgBgNVHRIEGTAXgRVkcml2ZXItcnVieUAxMGdlbi5jb20wDQYJ
|
28
|
-
KoZIhvcNAQEFBQADggEBAKjvumG2Fy9zAoSc1OEcmAqqOfzx1U+isGyEsz1rs5eT
|
29
|
-
HAIHsxaEdZTjSwDuqyelLDWJHWspeWU5pV5lepfI4cop29wwoPJIJ9Az2RMMbtdv
|
30
|
-
gFApVb6QX61OMenFeOdJ/QZ3n9xcrxJZFdvrXQ5GjEU2anq3dJhFeESwIMlfVJC7
|
31
|
-
7XrlMxizzH712DPfy65dMj0Y39qHdoWYKeCkEoj5UWNcHRK9xgaHJR6prlXrIhgb
|
32
|
-
o2UXDbWtz5PqoFd8EgNJAn3+BG1pwC9S9pVFG3WPucfAx/bE8iq/vvchHei5Y/Vo
|
33
|
-
aAz5f/hY4zFeYWvGDBHYEXE1rTN2hhMSyJscPcFbmz0=
|
34
|
-
-----END CERTIFICATE-----
|
35
|
-
date: 2015-09-10 00:00:00.000000000 Z
|
12
|
+
cert_chain: []
|
13
|
+
date: 2015-09-30 00:00:00.000000000 Z
|
36
14
|
dependencies:
|
37
15
|
- !ruby/object:Gem::Dependency
|
38
16
|
name: bson
|
@@ -59,6 +37,7 @@ files:
|
|
59
37
|
- README.md
|
60
38
|
- Rakefile
|
61
39
|
- bin/mongo_console
|
40
|
+
- lib/csasl/csasl.bundle
|
62
41
|
- lib/mongo.rb
|
63
42
|
- lib/mongo/address.rb
|
64
43
|
- lib/mongo/address/ipv4.rb
|
@@ -542,7 +521,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
542
521
|
version: '0'
|
543
522
|
requirements: []
|
544
523
|
rubyforge_project: mongo
|
545
|
-
rubygems_version: 2.4.
|
524
|
+
rubygems_version: 2.4.5.1
|
546
525
|
signing_key:
|
547
526
|
specification_version: 4
|
548
527
|
summary: Ruby driver for MongoDB
|
checksums.yaml.gz.sig
DELETED
data.tar.gz.sig
DELETED
Binary file
|
metadata.gz.sig
DELETED
Binary file
|