mongo 1.2.4 → 1.3.0.rc0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +13 -25
- data/Rakefile +9 -1
- data/docs/HISTORY.md +19 -0
- data/docs/RELEASES.md +33 -0
- data/docs/REPLICA_SETS.md +4 -3
- data/lib/mongo.rb +20 -2
- data/lib/mongo/collection.rb +15 -2
- data/lib/mongo/connection.rb +75 -14
- data/lib/mongo/cursor.rb +12 -4
- data/lib/mongo/db.rb +3 -3
- data/lib/mongo/exceptions.rb +3 -0
- data/lib/mongo/gridfs/grid_io.rb +88 -7
- data/lib/mongo/repl_set_connection.rb +29 -11
- data/lib/mongo/util/pool.rb +15 -6
- data/lib/mongo/util/timeout.rb +42 -0
- data/lib/mongo/util/uri_parser.rb +5 -1
- data/test/auxillary/fork_test.rb +30 -0
- data/test/bson/bson_test.rb +68 -27
- data/test/bson/byte_buffer_test.rb +11 -0
- data/test/bson/object_id_test.rb +14 -1
- data/test/bson/ordered_hash_test.rb +7 -0
- data/test/bson/timestamp_test.rb +24 -0
- data/test/collection_test.rb +41 -24
- data/test/connection_test.rb +33 -2
- data/test/conversions_test.rb +10 -11
- data/test/cursor_fail_test.rb +1 -1
- data/test/cursor_message_test.rb +1 -1
- data/test/cursor_test.rb +33 -4
- data/test/db_api_test.rb +13 -2
- data/test/db_test.rb +3 -3
- data/test/grid_file_system_test.rb +0 -1
- data/test/grid_io_test.rb +72 -1
- data/test/grid_test.rb +16 -16
- data/test/replica_sets/connect_test.rb +8 -0
- data/test/replica_sets/query_test.rb +10 -0
- data/test/support/hash_with_indifferent_access.rb +0 -13
- data/test/support_test.rb +0 -1
- data/test/test_helper.rb +27 -8
- data/test/timeout_test.rb +14 -0
- data/test/unit/collection_test.rb +1 -1
- data/test/unit/connection_test.rb +0 -13
- data/test/unit/cursor_test.rb +16 -6
- data/test/unit/db_test.rb +9 -11
- data/test/unit/repl_set_connection_test.rb +0 -13
- data/test/unit/safe_test.rb +1 -1
- metadata +15 -23
data/README.md
CHANGED
@@ -10,6 +10,7 @@ This documentation includes other articles of interest, include:
|
|
10
10
|
4. [GridFS in Ruby](http://api.mongodb.org/ruby/current/file.GridFS.html).
|
11
11
|
5. [Frequently Asked Questions](http://api.mongodb.org/ruby/current/file.FAQ.html).
|
12
12
|
6. [History](http://api.mongodb.org/ruby/current/file.HISTORY.html).
|
13
|
+
6. [Release plan](http://api.mongodb.org/ruby/current/file.RELEASES.html).
|
13
14
|
7. [Credits](http://api.mongodb.org/ruby/current/file.CREDITS.html).
|
14
15
|
|
15
16
|
Here's a quick code sample. Again, see the [MongoDB Ruby Tutorial](http://api.mongodb.org/ruby/current/file.TUTORIAL.html)
|
@@ -141,32 +142,11 @@ To set up a pooled connection to a single MongoDB instance:
|
|
141
142
|
Though the pooling architecture will undoubtedly evolve, it currently owes much credit
|
142
143
|
to the connection pooling implementations in ActiveRecord and PyMongo.
|
143
144
|
|
144
|
-
##
|
145
|
-
|
146
|
-
When Passenger and Unicorn are in smart spawning mode you need to be sure that child
|
147
|
-
processes will create a new connection to the database. In Passenger, this can be handled like so:
|
148
|
-
|
149
|
-
if defined?(PhusionPassenger)
|
150
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
151
|
-
if forked
|
152
|
-
# Reset all connection objects. How you do this depends on where
|
153
|
-
# you keep your connection object. In any case, call the #connect
|
154
|
-
# method on the connection object. For example:
|
155
|
-
# CONN.connect
|
156
|
-
#
|
157
|
-
# If you're using MongoMapper:
|
158
|
-
# MongoMapper.connection.connect
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
145
|
+
## Forking
|
162
146
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
# Handle reconnection
|
167
|
-
end
|
168
|
-
|
169
|
-
The above code should be put into a Rails initializer or similar initialization script.
|
147
|
+
Certain Ruby application servers work by forking, and it has long been necessary to
|
148
|
+
re-establish the child process's connection to the database after fork. But with the release
|
149
|
+
of v1.3.0, the Ruby driver detects forking and reconnects automatically.
|
170
150
|
|
171
151
|
## String Encoding
|
172
152
|
|
@@ -271,6 +251,14 @@ Notes:
|
|
271
251
|
* Cursors will timeout on the server after 10 minutes. If you need to keep a cursor
|
272
252
|
open for more than 10 minutes, specify `:timeout => false` when you create the cursor.
|
273
253
|
|
254
|
+
## Socket timeouts
|
255
|
+
|
256
|
+
The Ruby driver support timeouts on socket read operations. To enable them, set the
|
257
|
+
`:op_timeout` option when you create a `Mongo::Connection` object.
|
258
|
+
|
259
|
+
If implementing higher-level timeouts, using tools like `Rack::Timeout`, it's very important
|
260
|
+
to call `Mongo::Connection#close` to prevent the subsequent operation from receiving the previous
|
261
|
+
request.
|
274
262
|
|
275
263
|
# Testing
|
276
264
|
|
data/Rakefile
CHANGED
@@ -77,41 +77,49 @@ namespace :test do
|
|
77
77
|
Rake::TestTask.new(:rs) do |t|
|
78
78
|
t.test_files = FileList['test/replica_sets/*_test.rb']
|
79
79
|
t.verbose = true
|
80
|
+
t.ruby_opts << '-w'
|
80
81
|
end
|
81
82
|
|
82
83
|
Rake::TestTask.new(:unit) do |t|
|
83
84
|
t.test_files = FileList['test/unit/*_test.rb']
|
84
85
|
t.verbose = true
|
86
|
+
t.ruby_opts << '-w'
|
85
87
|
end
|
86
88
|
|
87
89
|
Rake::TestTask.new(:functional) do |t|
|
88
90
|
t.test_files = FileList['test/*_test.rb']
|
89
91
|
t.verbose = true
|
92
|
+
t.ruby_opts << '-w'
|
90
93
|
end
|
91
94
|
|
92
95
|
Rake::TestTask.new(:pooled_threading) do |t|
|
93
96
|
t.test_files = FileList['test/threading/*_test.rb']
|
94
97
|
t.verbose = true
|
98
|
+
t.ruby_opts << '-w'
|
95
99
|
end
|
96
100
|
|
97
101
|
Rake::TestTask.new(:auto_reconnect) do |t|
|
98
102
|
t.test_files = FileList['test/auxillary/autoreconnect_test.rb']
|
99
103
|
t.verbose = true
|
104
|
+
t.ruby_opts << '-w'
|
100
105
|
end
|
101
106
|
|
102
107
|
Rake::TestTask.new(:authentication) do |t|
|
103
108
|
t.test_files = FileList['test/auxillary/authentication_test.rb']
|
104
109
|
t.verbose = true
|
110
|
+
t.ruby_opts << '-w'
|
105
111
|
end
|
106
112
|
|
107
113
|
Rake::TestTask.new(:new_features) do |t|
|
108
114
|
t.test_files = FileList['test/auxillary/1.4_features.rb']
|
109
115
|
t.verbose = true
|
116
|
+
t.ruby_opts << '-w'
|
110
117
|
end
|
111
118
|
|
112
119
|
Rake::TestTask.new(:bson) do |t|
|
113
120
|
t.test_files = FileList['test/bson/*_test.rb']
|
114
121
|
t.verbose = true
|
122
|
+
t.ruby_opts << '-w'
|
115
123
|
end
|
116
124
|
|
117
125
|
task :drop_databases do |t|
|
@@ -138,7 +146,7 @@ task :ydoc do
|
|
138
146
|
require File.join(File.dirname(__FILE__), 'lib', 'mongo')
|
139
147
|
out = File.join('ydoc', Mongo::VERSION)
|
140
148
|
FileUtils.rm_rf('ydoc')
|
141
|
-
system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/HISTORY.md,docs/CREDITS.md,docs/1.0_UPGRADE.md"
|
149
|
+
system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/HISTORY.md,docs/CREDITS.md,docs/1.0_UPGRADE.md,docs/RELEASES.md"
|
142
150
|
end
|
143
151
|
|
144
152
|
namespace :bamboo do
|
data/docs/HISTORY.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# MongoDB Ruby Driver History
|
2
2
|
|
3
|
+
### 1.3.0.rc0
|
4
|
+
2011-3-29
|
5
|
+
|
6
|
+
* Add option to set timeouts on socket read calls. Use
|
7
|
+
the :op_timeout option when creating a new connection.
|
8
|
+
* Add StringIO methods to GridIO objects
|
9
|
+
* Support for BSON timestamp type with BSON::Timestamp
|
10
|
+
* Change the BSON binary subtype from 2 to 0
|
11
|
+
* Remove private method Connection#reset_conection
|
12
|
+
and deprecate public method ReplSetConnection#reset_connection
|
13
|
+
* ByteBuffer#== and OrderedHash#dup (FooBarWidget)
|
14
|
+
* Better check for UTF8 validity in Ruby 1.9
|
15
|
+
* Added previously removed Connection#host and Connection#port
|
16
|
+
* Added transformers to allow Mongo::Cursor to allow instantiated objects (jnunemaker)
|
17
|
+
* Automated reconnection on fork
|
18
|
+
* Added Cursor#next alias for Cursor#next_document
|
19
|
+
* Audit tests after enabling warnings (wpiekutowski)
|
20
|
+
* Various bug fixes thanks to FooBarWidget, Datanoise, Malitogeek
|
21
|
+
|
3
22
|
### 1.2.4
|
4
23
|
2011-2-23
|
5
24
|
|
data/docs/RELEASES.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# MongoDB Ruby Driver Release Plan
|
2
|
+
|
3
|
+
This is a description of a formalized release plan that will take effect
|
4
|
+
with version 1.3.0.
|
5
|
+
|
6
|
+
## Semantic versioning
|
7
|
+
|
8
|
+
The most significant difference is that releases will now adhere to the conventions of
|
9
|
+
[semantic versioning](http://semver.org). In particular, we will strictly abide by the
|
10
|
+
following release rules:
|
11
|
+
|
12
|
+
1. Patch versions of the driver (Z in x.y.Z) will be released only when backward-compatible bug fixes are introduced. A bug fix is defined as an internal change that fixes incorrect behavior.
|
13
|
+
|
14
|
+
2. Minor versions (Y in x.Y.z) will be released if new, backward-compatible functionality is introduced to the public API.
|
15
|
+
|
16
|
+
3. Major versions (X in X.y.z) will be incremented if any backward-incompatibl changes are introduced to the public API.
|
17
|
+
|
18
|
+
This policy will clearly indicate to users when an upgrade may affect their code. As a side effect, version numbers will climb more quickly than before.
|
19
|
+
|
20
|
+
|
21
|
+
## Release checklist
|
22
|
+
|
23
|
+
Before each relese to Rubygems.org, the following steps will be taken:
|
24
|
+
|
25
|
+
1. All driver tests will be run on Linux, OS X, and Windows via continuous integration system.
|
26
|
+
|
27
|
+
2. HISTORY file will document all significant commits.
|
28
|
+
|
29
|
+
3. Version number will be incremented per the semantic version spec described above.
|
30
|
+
|
31
|
+
4. Appropriate branches and tags will be created in Git repository, as necessary.
|
32
|
+
|
33
|
+
5. Docs will be updated to the latest version of the driver and posted [online](http://api.mongodb.org/ruby/current/index.html).
|
data/docs/REPLICA_SETS.md
CHANGED
@@ -6,12 +6,13 @@ Here follow a few considerations for those using the MongoDB Ruby driver with [r
|
|
6
6
|
|
7
7
|
First, make sure that you've configured and initialized a replica set.
|
8
8
|
|
9
|
-
Use `ReplSetConnection.new` to connect to a replica set
|
9
|
+
Use `ReplSetConnection.new` to connect to a replica set. This method, which accepts a variable number of arugments,
|
10
|
+
takes a list of seed nodes followed by any connection options. You'll want to specify at least two seed nodes. This gives
|
11
|
+
the driver more chances to connect in the event that any one seed node is offline. Once the driver connects, it will
|
12
|
+
cache the replica set topology as reported by the given seed node and use that information if a failover is later required.
|
10
13
|
|
11
14
|
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], ['n2.mydb.net', 27017], ['n3.mydb.net', 27017])
|
12
15
|
|
13
|
-
The driver will attempt to connect to a master node and, when found, will replace all seed nodes with known members of the replica set.
|
14
|
-
|
15
16
|
### Read slaves
|
16
17
|
|
17
18
|
If you want to read from a seconday node, you can pass :read_secondary => true to ReplSetConnection#new.
|
data/lib/mongo.rb
CHANGED
@@ -19,7 +19,7 @@
|
|
19
19
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
20
20
|
|
21
21
|
module Mongo
|
22
|
-
VERSION = "1.
|
22
|
+
VERSION = "1.3.0.rc0"
|
23
23
|
end
|
24
24
|
|
25
25
|
module Mongo
|
@@ -76,4 +76,22 @@ if RUBY_PLATFORM =~ /java/
|
|
76
76
|
end
|
77
77
|
require 'mongo/gridfs/grid_file_system'
|
78
78
|
|
79
|
-
|
79
|
+
# Use SystemTimer on Ruby 1.8
|
80
|
+
if !defined?(RUBY_ENGINE) || (RUBY_ENGINE == 'ruby' && RUBY_VERSION < '1.9.0')
|
81
|
+
begin
|
82
|
+
require 'system_timer'
|
83
|
+
if SystemTimer.method(:timeout).arity.abs != 2
|
84
|
+
raise LoadError
|
85
|
+
end
|
86
|
+
Mongo::TimeoutHandler = SystemTimer
|
87
|
+
rescue LoadError
|
88
|
+
warn "Could not load SystemTimer >= v1.2.0. Falling back to timeout.rb. " +
|
89
|
+
"SystemTimer is STRONGLY recommended for timeouts in Ruby 1.8.7. " +
|
90
|
+
"See http://ph7spot.com/blog/system-timer-1-2-release for details."
|
91
|
+
require 'timeout'
|
92
|
+
Mongo::TimeoutHandler = Timeout
|
93
|
+
end
|
94
|
+
else
|
95
|
+
require 'timeout'
|
96
|
+
Mongo::TimeoutHandler = Timeout
|
97
|
+
end
|
data/lib/mongo/collection.rb
CHANGED
@@ -157,6 +157,8 @@ module Mongo
|
|
157
157
|
# the normal cursor timeout behavior of the mongod process. When +false+, the returned cursor will never timeout. Note
|
158
158
|
# that disabling timeout will only work when #find is invoked with a block. This is to prevent any inadvertant failure to
|
159
159
|
# close the cursor, as the cursor is explicitly closed when block code finishes.
|
160
|
+
# @option opts [Block] :transformer (nil) a block for tranforming returned documents.
|
161
|
+
# This is normally used by object mappers to convert each returned document to an instance of a class.
|
160
162
|
#
|
161
163
|
# @raise [ArgumentError]
|
162
164
|
# if timeout is set to false and find is not invoked in a block
|
@@ -175,6 +177,7 @@ module Mongo
|
|
175
177
|
snapshot = opts.delete(:snapshot)
|
176
178
|
batch_size = opts.delete(:batch_size)
|
177
179
|
timeout = (opts.delete(:timeout) == false) ? false : true
|
180
|
+
transformer = opts.delete(:transformer)
|
178
181
|
|
179
182
|
if timeout == false && !block_given?
|
180
183
|
raise ArgumentError, "Collection#find must be invoked with a block when timeout is disabled."
|
@@ -188,8 +191,18 @@ module Mongo
|
|
188
191
|
|
189
192
|
raise RuntimeError, "Unknown options [#{opts.inspect}]" unless opts.empty?
|
190
193
|
|
191
|
-
cursor = Cursor.new(self,
|
192
|
-
:
|
194
|
+
cursor = Cursor.new(self, {
|
195
|
+
:selector => selector,
|
196
|
+
:fields => fields,
|
197
|
+
:skip => skip,
|
198
|
+
:limit => limit,
|
199
|
+
:order => sort,
|
200
|
+
:hint => hint,
|
201
|
+
:snapshot => snapshot,
|
202
|
+
:timeout => timeout,
|
203
|
+
:batch_size => batch_size,
|
204
|
+
:transformer => transformer,
|
205
|
+
})
|
193
206
|
|
194
207
|
if block_given?
|
195
208
|
yield cursor
|
data/lib/mongo/connection.rb
CHANGED
@@ -68,6 +68,8 @@ module Mongo
|
|
68
68
|
# @option opts [Float] :timeout (5.0) When all of the connections a pool are checked out,
|
69
69
|
# this is the number of seconds to wait for a new connection to be released before throwing an exception.
|
70
70
|
# Note: this setting is relevant only for multi-threaded applications (which in Ruby are rare).
|
71
|
+
# @option opts [Float] :op_timeout (nil) The number of seconds to wait for a read operation to time out.
|
72
|
+
# Disabled by default.
|
71
73
|
#
|
72
74
|
# @example localhost, 27017
|
73
75
|
# Connection.new
|
@@ -157,6 +159,20 @@ module Mongo
|
|
157
159
|
end
|
158
160
|
end
|
159
161
|
|
162
|
+
# The host name used for this connection.
|
163
|
+
#
|
164
|
+
# @return [String]
|
165
|
+
def host
|
166
|
+
@primary_pool.host
|
167
|
+
end
|
168
|
+
|
169
|
+
# The port used for this connection.
|
170
|
+
#
|
171
|
+
# @return [Integer]
|
172
|
+
def port
|
173
|
+
@primary_pool.port
|
174
|
+
end
|
175
|
+
|
160
176
|
# Fsync, then lock the mongod process against writes. Use this to get
|
161
177
|
# the datafiles in a state safe for snapshotting, backing up, etc.
|
162
178
|
#
|
@@ -329,13 +345,22 @@ module Mongo
|
|
329
345
|
self["admin"].command(oh)
|
330
346
|
end
|
331
347
|
|
332
|
-
|
348
|
+
# Checks if a server is alive. This command will return immediately
|
349
|
+
# even if the server is in a lock.
|
350
|
+
#
|
351
|
+
# @return [Hash]
|
352
|
+
def ping
|
353
|
+
self["admin"].command({:ping => 1})
|
354
|
+
end
|
355
|
+
|
356
|
+
# Get the build information for the current connection.
|
333
357
|
#
|
334
358
|
# @return [Hash]
|
335
359
|
def server_info
|
336
360
|
self["admin"].command({:buildinfo => 1})
|
337
361
|
end
|
338
362
|
|
363
|
+
|
339
364
|
# Get the build version of the current server.
|
340
365
|
#
|
341
366
|
# @return [Mongo::ServerVersion]
|
@@ -450,7 +475,7 @@ module Mongo
|
|
450
475
|
#
|
451
476
|
# @raise [ConnectionFailure] if unable to connect to any host or port.
|
452
477
|
def connect
|
453
|
-
|
478
|
+
close
|
454
479
|
|
455
480
|
config = check_is_master(@host_to_try)
|
456
481
|
if config
|
@@ -482,6 +507,22 @@ module Mongo
|
|
482
507
|
@primary_pool && @primary_pool.host && @primary_pool.port
|
483
508
|
end
|
484
509
|
|
510
|
+
# Determine if the connection is active. In a normal case the *server_info* operation
|
511
|
+
# will be performed without issues, but if the connection was dropped by the server or
|
512
|
+
# for some reason the sockets are unsynchronized, a ConnectionFailure will be raised and
|
513
|
+
# the return will be false.
|
514
|
+
#
|
515
|
+
# @return [Boolean]
|
516
|
+
def active?
|
517
|
+
return false unless connected?
|
518
|
+
|
519
|
+
ping
|
520
|
+
true
|
521
|
+
|
522
|
+
rescue ConnectionFailure
|
523
|
+
false
|
524
|
+
end
|
525
|
+
|
485
526
|
# Determine whether we're reading from a primary node. If false,
|
486
527
|
# this connection connects to a secondary node and @slave_ok is true.
|
487
528
|
#
|
@@ -495,6 +536,7 @@ module Mongo
|
|
495
536
|
def close
|
496
537
|
@primary_pool.close if @primary_pool
|
497
538
|
@primary_pool = nil
|
539
|
+
@primary = nil
|
498
540
|
end
|
499
541
|
|
500
542
|
# Returns the maximum BSON object size as returned by the core server.
|
@@ -559,6 +601,9 @@ module Mongo
|
|
559
601
|
@pool_size = opts[:pool_size] || 1
|
560
602
|
@timeout = opts[:timeout] || 5.0
|
561
603
|
|
604
|
+
# Timeout on socket read operation.
|
605
|
+
@op_timeout = opts[:op_timeout] || nil
|
606
|
+
|
562
607
|
# Mutex for synchronizing pool access
|
563
608
|
@connection_mutex = Mutex.new
|
564
609
|
|
@@ -611,7 +656,7 @@ module Mongo
|
|
611
656
|
msg += payload.values_at(:selector, :document, :documents, :fields ).compact.map(&:inspect).join(', ') + ")"
|
612
657
|
msg += ".skip(#{payload[:skip]})" if payload[:skip]
|
613
658
|
msg += ".limit(#{payload[:limit]})" if payload[:limit]
|
614
|
-
msg += ".sort(#{payload[:
|
659
|
+
msg += ".sort(#{payload[:order]})" if payload[:order]
|
615
660
|
@logger.debug "MONGODB #{msg}"
|
616
661
|
end
|
617
662
|
|
@@ -624,7 +669,6 @@ module Mongo
|
|
624
669
|
# TODO: evaluate whether this method is actually necessary
|
625
670
|
def reset_connection
|
626
671
|
close
|
627
|
-
@primary = nil
|
628
672
|
end
|
629
673
|
|
630
674
|
def check_is_master(node)
|
@@ -793,20 +837,37 @@ module Mongo
|
|
793
837
|
# Requires length and an available socket.
|
794
838
|
def receive_message_on_socket(length, socket)
|
795
839
|
begin
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
chunk = new_binary_string
|
801
|
-
while message.length < length
|
802
|
-
socket.read(length - message.length, chunk)
|
803
|
-
raise ConnectionFailure, "connection closed" unless chunk.length > 0
|
804
|
-
message << chunk
|
840
|
+
if @op_timeout
|
841
|
+
message = nil
|
842
|
+
Mongo::TimeoutHandler.timeout(@op_timeout, OperationTimeout) do
|
843
|
+
message = receive_data(length, socket)
|
805
844
|
end
|
845
|
+
else
|
846
|
+
message = receive_data(length, socket)
|
806
847
|
end
|
807
848
|
rescue => ex
|
808
849
|
close
|
809
|
-
|
850
|
+
|
851
|
+
if ex.class == OperationTimeout
|
852
|
+
raise OperationTimeout, "Timed out waiting on socket read."
|
853
|
+
else
|
854
|
+
raise ConnectionFailure, "Operation failed with the following exception: #{ex}"
|
855
|
+
end
|
856
|
+
end
|
857
|
+
message
|
858
|
+
end
|
859
|
+
|
860
|
+
def receive_data(length, socket)
|
861
|
+
message = new_binary_string
|
862
|
+
socket.read(length, message)
|
863
|
+
raise ConnectionFailure, "connection closed" unless message && message.length > 0
|
864
|
+
if message.length < length
|
865
|
+
chunk = new_binary_string
|
866
|
+
while message.length < length
|
867
|
+
socket.read(length - message.length, chunk)
|
868
|
+
raise ConnectionFailure, "connection closed" unless chunk.length > 0
|
869
|
+
message << chunk
|
870
|
+
end
|
810
871
|
end
|
811
872
|
message
|
812
873
|
end
|
data/lib/mongo/cursor.rb
CHANGED
@@ -23,7 +23,7 @@ module Mongo
|
|
23
23
|
|
24
24
|
attr_reader :collection, :selector, :fields,
|
25
25
|
:order, :hint, :snapshot, :timeout,
|
26
|
-
:full_collection_name
|
26
|
+
:full_collection_name, :transformer
|
27
27
|
|
28
28
|
# Create a new cursor.
|
29
29
|
#
|
@@ -34,6 +34,8 @@ module Mongo
|
|
34
34
|
#
|
35
35
|
# @core cursors constructor_details
|
36
36
|
def initialize(collection, opts={})
|
37
|
+
@cursor_id = nil
|
38
|
+
|
37
39
|
@db = collection.db
|
38
40
|
@collection = collection
|
39
41
|
@connection = @db.connection
|
@@ -52,6 +54,7 @@ module Mongo
|
|
52
54
|
@tailable = opts[:tailable] || false
|
53
55
|
@closed = false
|
54
56
|
@query_run = false
|
57
|
+
@transformer = opts[:transformer]
|
55
58
|
batch_size(opts[:batch_size] || 0)
|
56
59
|
|
57
60
|
@full_collection_name = "#{@collection.db.name}.#{@collection.name}"
|
@@ -86,8 +89,13 @@ module Mongo
|
|
86
89
|
raise OperationFailure, err
|
87
90
|
end
|
88
91
|
|
89
|
-
|
92
|
+
if @transformer.nil?
|
93
|
+
doc
|
94
|
+
else
|
95
|
+
@transformer.call(doc) if doc
|
96
|
+
end
|
90
97
|
end
|
98
|
+
alias :next :next_document
|
91
99
|
|
92
100
|
# Reset this cursor on the server. Cursor options, such as the
|
93
101
|
# query string and the values for skip and limit, are preserved.
|
@@ -307,8 +315,8 @@ module Mongo
|
|
307
315
|
def query_options_hash
|
308
316
|
{ :selector => @selector,
|
309
317
|
:fields => @fields,
|
310
|
-
:skip => @
|
311
|
-
:limit => @
|
318
|
+
:skip => @skip,
|
319
|
+
:limit => @limit,
|
312
320
|
:order => @order,
|
313
321
|
:hint => @hint,
|
314
322
|
:snapshot => @snapshot,
|