moped 1.2.1 → 1.2.2
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.
- data/CHANGELOG.md +11 -1
- data/lib/moped/errors.rb +7 -0
- data/lib/moped/node.rb +64 -30
- data/lib/moped/protocol/reply.rb +14 -0
- data/lib/moped/query.rb +4 -1
- data/lib/moped/version.rb +1 -1
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -4,10 +4,20 @@
|
|
4
4
|
|
5
5
|
### New Features
|
6
6
|
|
7
|
-
## 1.2.2
|
7
|
+
## 1.2.2
|
8
8
|
|
9
9
|
### Resolved Issues
|
10
10
|
|
11
|
+
* \#73 Raise a `Moped::Errors::CursorNotFound` on long running queries where
|
12
|
+
the cursor was killed by the server. (Marius Podwyszynski)
|
13
|
+
|
14
|
+
* \#72 Reauthenticate properly when an `rs.stepDown()` occurs in the middle of
|
15
|
+
cursor execution.
|
16
|
+
|
17
|
+
* \#71 When DNS cannot resolve on node initialization, the node will be flagged
|
18
|
+
as down instead of raising a `SocketError`. On subsequent refreshes Moped will
|
19
|
+
attempt to resolve the DNS again to determine if the node can be brought up.
|
20
|
+
|
11
21
|
## 1.2.1
|
12
22
|
|
13
23
|
### Resolved Issues
|
data/lib/moped/errors.rb
CHANGED
@@ -97,6 +97,13 @@ module Moped
|
|
97
97
|
# Exception raised on invalid queries.
|
98
98
|
class QueryFailure < MongoError; end
|
99
99
|
|
100
|
+
# Exception raised if the cursor could not be found.
|
101
|
+
class CursorNotFound < MongoError
|
102
|
+
def initialize(operation, cursor_id)
|
103
|
+
super(operation, {"errmsg" => "cursor #{cursor_id} not found"})
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
100
107
|
# @api private
|
101
108
|
#
|
102
109
|
# Internal exception raised by Node#ensure_primary and captured by
|
data/lib/moped/node.rb
CHANGED
@@ -125,7 +125,7 @@ module Moped
|
|
125
125
|
# Someone else wrapped this in an #ensure_primary block, so let the
|
126
126
|
# reconfiguration exception bubble up.
|
127
127
|
raise
|
128
|
-
rescue Errors::OperationFailure, Errors::AuthenticationFailure, Errors::QueryFailure
|
128
|
+
rescue Errors::OperationFailure, Errors::AuthenticationFailure, Errors::QueryFailure, Errors::CursorNotFound
|
129
129
|
# These exceptions are "expected" in the normal course of events, and
|
130
130
|
# don't necessitate disconnecting.
|
131
131
|
raise
|
@@ -179,12 +179,15 @@ module Moped
|
|
179
179
|
# @param [ Collection ] collection The collection to get more from.
|
180
180
|
# @param [ Integer ] cursor_id The id of the cursor on the server.
|
181
181
|
# @param [ Integer ] limit The number of documents to limit.
|
182
|
+
# @raise [ CursorNotFound ] if the cursor has been killed
|
182
183
|
#
|
183
184
|
# @return [ Message ] The result of the operation.
|
184
185
|
#
|
185
186
|
# @since 1.0.0
|
186
187
|
def get_more(database, collection, cursor_id, limit)
|
187
|
-
process(Protocol::GetMore.new(database, collection, cursor_id, limit))
|
188
|
+
reply = process(Protocol::GetMore.new(database, collection, cursor_id, limit))
|
189
|
+
raise Moped::Errors::CursorNotFound.new("GET MORE", cursor_id) if reply.cursor_not_found?
|
190
|
+
reply
|
188
191
|
end
|
189
192
|
|
190
193
|
# Get the hash identifier for the node.
|
@@ -209,17 +212,12 @@ module Moped
|
|
209
212
|
# @since 1.0.0
|
210
213
|
def initialize(address)
|
211
214
|
@address = address
|
212
|
-
|
213
|
-
host, port = address.split(":")
|
214
|
-
@ip_address = ::Socket.getaddrinfo(host, nil, ::Socket::AF_INET, ::Socket::SOCK_STREAM).first[3]
|
215
|
-
@port = port.to_i
|
216
|
-
@resolved_address = "#{@ip_address}:#{@port}"
|
217
|
-
|
218
215
|
@timeout = 5
|
219
216
|
@down_at = nil
|
220
217
|
@refreshed_at = nil
|
221
218
|
@primary = nil
|
222
219
|
@secondary = nil
|
220
|
+
resolve_address
|
223
221
|
end
|
224
222
|
|
225
223
|
# Insert documents into the database.
|
@@ -340,9 +338,20 @@ module Moped
|
|
340
338
|
def query(database, collection, selector, options = {})
|
341
339
|
operation = Protocol::Query.new(database, collection, selector, options)
|
342
340
|
|
343
|
-
process
|
344
|
-
if reply.
|
345
|
-
|
341
|
+
process(operation) do |reply|
|
342
|
+
if reply.query_failed?
|
343
|
+
if reply.unauthorized? && auth.has_key?[database]
|
344
|
+
# If we got here, most likely this is the case of Moped
|
345
|
+
# authenticating successfully against the node originally, but the
|
346
|
+
# node has been reset or gone down and come back up. The most
|
347
|
+
# common case here is a rs.stepDown() which will reinitialize the
|
348
|
+
# connection. In this case we need to requthenticate and try again,
|
349
|
+
# otherwise we'll just raise the error to the user.
|
350
|
+
login(database, *auth[database])
|
351
|
+
query(database, collection, selector, options)
|
352
|
+
else
|
353
|
+
raise Errors::QueryFailure.new(operation, reply.documents.first)
|
354
|
+
end
|
346
355
|
end
|
347
356
|
reply
|
348
357
|
end
|
@@ -363,25 +372,27 @@ module Moped
|
|
363
372
|
#
|
364
373
|
# @since 1.0.0
|
365
374
|
def refresh
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
375
|
+
if resolve_address
|
376
|
+
info = command("admin", ismaster: 1)
|
377
|
+
|
378
|
+
@refreshed_at = Time.now
|
379
|
+
primary = true if info["ismaster"]
|
380
|
+
secondary = true if info["secondary"]
|
381
|
+
|
382
|
+
peers = []
|
383
|
+
peers.push(info["primary"]) if info["primary"]
|
384
|
+
peers.concat(info["hosts"]) if info["hosts"]
|
385
|
+
peers.concat(info["passives"]) if info["passives"]
|
386
|
+
peers.concat(info["arbiters"]) if info["arbiters"]
|
387
|
+
|
388
|
+
@peers = peers.map { |peer| Node.new(peer) }
|
389
|
+
@primary, @secondary = primary, secondary
|
390
|
+
@arbiter = info["arbiterOnly"]
|
391
|
+
@passive = info["passive"]
|
392
|
+
|
393
|
+
if !primary && Threaded.executing?(:ensure_primary)
|
394
|
+
raise Errors::ReplicaSetReconfigured, "#{inspect} is no longer the primary node."
|
395
|
+
end
|
385
396
|
end
|
386
397
|
end
|
387
398
|
|
@@ -548,5 +559,28 @@ module Moped
|
|
548
559
|
logger.debug indent + last.log_inspect + runtime
|
549
560
|
end
|
550
561
|
end
|
562
|
+
|
563
|
+
def resolve_address
|
564
|
+
unless ip_address
|
565
|
+
begin
|
566
|
+
parse_address and true
|
567
|
+
rescue SocketError
|
568
|
+
if logger = Moped.logger
|
569
|
+
logger.warn " MOPED: Could not resolve IP address for #{address}"
|
570
|
+
end
|
571
|
+
@down_at = Time.new
|
572
|
+
false
|
573
|
+
end
|
574
|
+
else
|
575
|
+
true
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
def parse_address
|
580
|
+
host, port = address.split(":")
|
581
|
+
@port = port.to_i
|
582
|
+
@ip_address = ::Socket.getaddrinfo(host, nil, ::Socket::AF_INET, ::Socket::SOCK_STREAM).first[3]
|
583
|
+
@resolved_address = "#{@ip_address}:#{@port}"
|
584
|
+
end
|
551
585
|
end
|
552
586
|
end
|
data/lib/moped/protocol/reply.rb
CHANGED
@@ -13,6 +13,8 @@ module Moped
|
|
13
13
|
class Reply
|
14
14
|
include Message
|
15
15
|
|
16
|
+
UNAUTHORIZED = 10057
|
17
|
+
|
16
18
|
# @attribute
|
17
19
|
# @return [Number] the length of the message
|
18
20
|
int32 :length
|
@@ -53,6 +55,18 @@ module Moped
|
|
53
55
|
|
54
56
|
finalize
|
55
57
|
|
58
|
+
def cursor_not_found?
|
59
|
+
flags.include?(:cursor_not_found)
|
60
|
+
end
|
61
|
+
|
62
|
+
def query_failed?
|
63
|
+
flags.include?(:query_failure)
|
64
|
+
end
|
65
|
+
|
66
|
+
def unauthorized?
|
67
|
+
documents.first["code"] == UNAUTHORIZED
|
68
|
+
end
|
69
|
+
|
56
70
|
class << self
|
57
71
|
|
58
72
|
# Consumes a buffer, returning the deserialized Reply message.
|
data/lib/moped/query.rb
CHANGED
@@ -202,9 +202,12 @@ module Moped
|
|
202
202
|
command[:fields] = operation.fields if operation.fields
|
203
203
|
command[:update] = change unless options[:remove]
|
204
204
|
|
205
|
-
session.with(consistency: :strong) do |sess|
|
205
|
+
result = session.with(consistency: :strong) do |sess|
|
206
206
|
sess.command(command)["value"]
|
207
207
|
end
|
208
|
+
|
209
|
+
# Keeping moped compatibility with mongodb >= 2.2.0-rc0
|
210
|
+
options[:upsert] && !result ? [] : result
|
208
211
|
end
|
209
212
|
|
210
213
|
# Remove a single document matching the query's selector.
|
data/lib/moped/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moped
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A MongoDB driver for Ruby.
|
15
15
|
email:
|
@@ -85,7 +85,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
85
|
version: '0'
|
86
86
|
segments:
|
87
87
|
- 0
|
88
|
-
hash:
|
88
|
+
hash: 3008607768252365192
|
89
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
90
|
none: false
|
91
91
|
requirements:
|
@@ -94,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
94
|
version: '0'
|
95
95
|
segments:
|
96
96
|
- 0
|
97
|
-
hash:
|
97
|
+
hash: 3008607768252365192
|
98
98
|
requirements: []
|
99
99
|
rubyforge_project:
|
100
100
|
rubygems_version: 1.8.24
|