moped 1.0.0.rc → 1.0.0

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.

Files changed (45) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/README.md +32 -467
  3. data/lib/moped.rb +0 -1
  4. data/lib/moped/bson.rb +3 -0
  5. data/lib/moped/bson/binary.rb +4 -4
  6. data/lib/moped/bson/code.rb +12 -10
  7. data/lib/moped/bson/extensions.rb +64 -54
  8. data/lib/moped/bson/extensions/array.rb +9 -6
  9. data/lib/moped/bson/extensions/boolean.rb +1 -1
  10. data/lib/moped/bson/extensions/false_class.rb +5 -2
  11. data/lib/moped/bson/extensions/float.rb +1 -2
  12. data/lib/moped/bson/extensions/hash.rb +4 -5
  13. data/lib/moped/bson/extensions/integer.rb +2 -4
  14. data/lib/moped/bson/extensions/nil_class.rb +1 -2
  15. data/lib/moped/bson/extensions/object.rb +13 -0
  16. data/lib/moped/bson/extensions/regexp.rb +5 -6
  17. data/lib/moped/bson/extensions/string.rb +24 -13
  18. data/lib/moped/bson/extensions/symbol.rb +12 -14
  19. data/lib/moped/bson/extensions/time.rb +4 -4
  20. data/lib/moped/bson/extensions/true_class.rb +5 -2
  21. data/lib/moped/bson/max_key.rb +1 -2
  22. data/lib/moped/bson/min_key.rb +1 -2
  23. data/lib/moped/bson/object_id.rb +44 -4
  24. data/lib/moped/bson/types.rb +1 -1
  25. data/lib/moped/cluster.rb +13 -5
  26. data/lib/moped/collection.rb +5 -1
  27. data/lib/moped/connection.rb +4 -4
  28. data/lib/moped/database.rb +58 -29
  29. data/lib/moped/logging.rb +3 -3
  30. data/lib/moped/node.rb +35 -6
  31. data/lib/moped/protocol/command.rb +1 -4
  32. data/lib/moped/protocol/delete.rb +2 -0
  33. data/lib/moped/protocol/get_more.rb +16 -1
  34. data/lib/moped/protocol/insert.rb +2 -0
  35. data/lib/moped/protocol/kill_cursors.rb +2 -0
  36. data/lib/moped/protocol/message.rb +31 -12
  37. data/lib/moped/protocol/query.rb +15 -3
  38. data/lib/moped/protocol/reply.rb +6 -4
  39. data/lib/moped/protocol/update.rb +2 -0
  40. data/lib/moped/query.rb +60 -5
  41. data/lib/moped/session.rb +53 -17
  42. data/lib/moped/session/context.rb +17 -7
  43. data/lib/moped/threaded.rb +2 -1
  44. data/lib/moped/version.rb +1 -1
  45. metadata +11 -6
@@ -0,0 +1,11 @@
1
+ # Overview
2
+
3
+ ## 1.1.0 (branch: master)
4
+
5
+ ### New Features
6
+
7
+ ### Resolved Issues
8
+
9
+ ## 1.0.1
10
+
11
+ ### Resolved Issues
data/README.md CHANGED
@@ -4,483 +4,48 @@ Moped [![Build Status](https://secure.travis-ci.org/mongoid/moped.png?branch=mas
4
4
  Moped is a MongoDB driver for Ruby, which exposes a simple, elegant, and fast
5
5
  API.
6
6
 
7
+ Project Tracking
8
+ ----------------
9
+
10
+ * [Mongoid Google Group](http://groups.google.com/group/mongoid)
11
+ * [Moped Website and Documentation](http://mongoid.org/en/moped/)
12
+
7
13
  Compatibility
8
14
  -------------
9
15
 
10
16
  Moped is tested against MRI 1.9.2, 1.9.3, 2.0.0, and JRuby (1.9).
11
17
 
12
- Usage
13
- -----
14
-
15
- ```ruby
16
- session = Moped::Session.new %w[127.0.0.1:27017]
17
- session.use "echo_test"
18
-
19
- session.with(safe: true) do |safe|
20
- safe[:artists].insert(name: "Syd Vicious"
21
- end
22
-
23
- session[:artists].find(name: "Syd Vicious").
24
- update(
25
- :$push => { instruments: { name: "Bass" } }
26
- )
27
- ```
28
-
29
- ## Features
30
-
31
- * Automated replica set node discovery and failover.
32
- * No C or Java extensions
33
- * No external dependencies
34
- * Simple, stable, public API.
35
-
36
- ### Unsupported Features
37
-
38
- * GridFS
39
- * Map/Reduce
40
-
41
- These features are possible to implement, but outside the scope of Moped's
42
- goals. Consider them perfect opportunities to write a companion gem!
43
-
44
- # Project Breakdown
45
-
46
- Moped is composed of three parts: an implementation of the [BSON
47
- specification](http://bsonspec.org/), an implementation of the [Mongo Wire
48
- Protocol](http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol), and the
49
- driver itself. An overview of the first two follows now, and after that more
50
- information about the driver.
51
-
52
- ## Moped::BSON
53
-
54
- `Moped::BSON` is the namespace for Moped's BSON implementation. It's
55
- implemented in pure (but fast) ruby. The public entry point into the BSON
56
- module is `BSON::Document`, which is just subclass of `Hash`, but exposes two
57
- class methods: `serialize` and `deserialize`. `serialize` accepts a
58
- BSON::Document (or Hash) and returns the serialized BSON representation.
59
- `deserialize` does the opposite: it reads data from an IO-like input and
60
- returns a deserialized BSON::Document.
61
-
62
- ### Moped::BSON::ObjectId
63
-
64
- The `ObjectId` class is used for generating and interacting with Mongo's ids.
65
-
66
- ```ruby
67
- id = Moped::BSON::ObjectId.new # => 4f8583b5e5a4e46a64000002
68
- id.generation_time # => 2012-04-11 13:14:29 UTC
69
- id == Moped::BSON::ObjectId.from_string(id.to_s) # => true
70
- ```
71
-
72
- <table><tbody>
73
-
74
- <tr><th>new</th>
75
- <td>Creates a new object id.</td></tr>
76
-
77
- <tr><th>from_string</th>
78
- <td>Creates a new object id from an object id string.
79
- <br>
80
- <code>Moped::BSON::ObjectId.from_string("4f8d8c66e5a4e45396000009")</code>
81
- </td></tr>
82
-
83
- <tr><th>from_time</th>
84
- <td>Creates a new object id from a time.
85
- <br>
86
- <code>Moped::BSON::ObjectId.from_time(Time.new)</code>
87
- </td></tr>
88
-
89
- <tr><th>legal?</th>
90
- <td>Validates an object id string.
91
- <br>
92
- <code>Moped::BSON::ObjectId.legal?("4f8d8c66e5a4e45396000009")</code>
93
- </td></tr>
94
-
95
- </tbody></table>
96
-
97
- ### Moped::BSON::Code
98
-
99
- The `Code` class is used for working with javascript on the server.
100
-
101
- ```ruby
102
- Moped::BSON::Code.new("function () { return this.name }")
103
- Moped::BSON::Code.new("function (s) { return s.prefix + this.name }",
104
- prefix: "_"
105
- )
106
- ```
107
-
108
- ### Moped::BSON::Binary
109
-
110
- The `Binary` class allows you to persist binary data to the server, and
111
- supports the following types: `:generic`, `:function`, `:old`, `:uuid`, `:md5`,
112
- and `:user`. Note that `:old` is deprecated, but still present to support
113
- legacy data.
114
-
115
- ```ruby
116
- Moped::BSON::Binary.new(:md5, Digest::MD5.digest(__FILE__))
117
- ```
118
-
119
- ## Moped::Protocol
120
-
121
- `Moped::Protocol` is the namespace for Moped's implementation of the Mongo Wire
122
- Protocol. Its public API consists of classes representing each type of message
123
- in the protocol: `Delete`, `GetMore`, `Insert`, `KillCursors`, `Query`,
124
- `Reply`, `Update`, and a convenience class `Command`.
125
-
126
- You should never have to worry about protocol objects, but more details can be
127
- found in the API documentation if you're interested.
128
-
129
- # Driver API
130
-
131
- This is the core, public API for Moped. It lives almost entirely in four classes:
132
-
133
- * `Session`: the root object for all interactions with mongo (c.f., `db` in the
134
- mongo shell).
135
- * `Collection`: for working with collections in the context of a session
136
- * `Indexes`: for manipulating and inspecting a collection's indexes
137
- * `Query`: for querying, as well as modifying existing data.
138
-
139
- What follows is a "whirlwind" overview of the Moped driver API. For details on
140
- additional options, and more examples, use the [generated API
141
- docs](http://rubydoc.info/github/mongoid/moped/master/frames).
142
-
143
- ## Session
144
-
145
- ### Example
146
- ```ruby
147
- session = Moped::Session.new %w[127.0.0.1:27017 127.0.0.1:27018 127.0.0.1:27019]
148
- session.use :moped_test
149
- session.command ping: 1 # => {"ok"=>1.0}
150
-
151
- session.with(safe: { w: 2, wtimeout: 5 }) do |safe_session|
152
- safe_session[:users].find.remove_all
153
- end
154
-
155
- session.with(database: "important_db", consistency: :strong) do |session|
156
- session[:users].find.one
157
- end
158
- ```
159
-
160
- ### API
161
- <table><tbody>
162
-
163
- <tr><th>use</th>
164
- <td>Set the current database<br>
165
- <code>session.use :my_app_test</code></td></tr>
166
-
167
- <tr><th>with</th>
168
- <td>Return or yield a copy of session with different options.<br>
169
- <code>session.with(safe: true) { |s| ... }</code><br>
170
- <code>session.with(database: "admin").command(...)</code></td></tr>
171
-
172
- <tr><th>[]</th>
173
- <td>Choose a collection in the current database.<br>
174
- <code>session[:people]</code></td></tr>
175
-
176
- <tr><th>drop</th>
177
- <td>Drop the current database<br>
178
- <code>session.drop</code></td></tr>
179
-
180
- <tr><th>command</th>
181
- <td>Run a command on the current database.<br>
182
- <code>session.command(ping: 1)</code></td></tr>
183
-
184
- <tr><th>login</th>
185
- <td>Log in to the current database.<br>
186
- <code>session.login(username, password)</code></td></tr>
187
-
188
- <tr><th>logout</th>
189
- <td>Log out from the current database.<br>
190
- <code>session.logout</code></td></tr>
191
-
192
- </tbody></table>
193
-
194
- ## Collection
195
-
196
- ### Example
197
- ```ruby
198
- users = session[:users]
199
- users.drop
200
- users.find.count # => 0.0
201
-
202
- users.indexes.create({name: 1}, {unique: true})
203
-
204
- users.insert(name: "John")
205
- users.find.count # => 1.0
206
-
207
- users.insert(name: "John")
208
- users.find.count # => 1.0
209
-
210
- session.with(safe: true) do |session|
211
- session[:users].insert(name: "John")
212
- end # raises Moped::Errors::OperationFailure
213
- ```
214
-
215
- ### API
216
- <table><tbody>
217
-
218
- <tr><th>drop</th>
219
- <td>Drop the collection<br>
220
- <code>users.drop</code></td></tr>
221
-
222
- <tr><th>indexes</th>
223
- <td>Access information about this collection's indexes<br>
224
- <code>users.indexes</code></td></tr>
225
-
226
- <tr><th>find</th>
227
- <td>Build a query on the collection<br>
228
- <code>users.find(name: "John")</code></td></tr>
229
-
230
- <tr><th>insert</th>
231
- <td>Insert one or multiple documents.<br>
232
- <code>users.insert(name: "John")</code><br>
233
- <code>users.insert([{name: "John"}, {name: "Mary"}])</code></td></tr>
234
-
235
- </tbody></table>
236
-
237
- ## Index
238
-
239
- ### Example
240
- ```ruby
241
- session[:users].indexes.create(name: 1)
242
- session[:users].indexes.create(
243
- { name: 1, location: "2d" },
244
- { unique: true }
245
- )
246
- session[:users].indexes[name: 1]
247
- # => {"v"=>1, "key"=>{"name"=>1}, "ns"=>"moped_test.users", "name"=>"name_1" }
248
-
249
- session[:users].indexes.drop(name: 1)
250
- session[:users].indexes[name: 1] # => nil
251
- ```
252
-
253
- ### API
254
- <table><tbody>
255
-
256
- <tr><th>[]</th>
257
- <td>Get an index by its spec.<br>
258
- <code>indexes[id: 1]</code></td></tr>
259
-
260
- <tr><th>create</th>
261
- <td>Create an index<br>
262
- <code>indexes.create({name: 1}, {unique: true})</code></td></tr>
263
-
264
- <tr><th>drop</th>
265
- <td>Drop one or all indexes<br>
266
- <code>indexes.drop</code><br>
267
- <code>indexes.drop(name: 1)</code></td></tr>
268
-
269
- <tr><th>each</th>
270
- <td>Yield each index<br>
271
- <code>indexes.each { |idx| }</code></td></tr>
272
-
273
- </tbody></table>
274
-
275
- ## Query
276
-
277
- ### Example
278
- ```ruby
279
- users = session[:users]
280
-
281
- users.insert(name: "John")
282
- users.find.count # => 1
283
-
284
- users.find(name: "Mary").upsert(name: "Mary")
285
- users.find.count # => 2
286
-
287
- users.find.skip(1).limit(1).sort(name: -1).one
288
- # => {"_id" => <...>, "name" => "John" }
289
-
290
- scope = users.find(name: "Mary").select(_id: 0, name: 1)
291
- scope.one # => {"name" => "Mary" }
292
- scope.remove
293
- scope.one # nil
294
- ```
295
-
296
- ### API
297
- <table><tbody>
298
-
299
- <tr><th>limit</th>
300
- <td>Set the limit for this query.<br>
301
- <code>query.limit(5)</code></td></tr>
302
-
303
- <tr><th>skip</th>
304
- <td>Set the offset for this query.<br>
305
- <code>query.skip(5)</code></td></tr>
306
-
307
- <tr><th>sort</th>
308
- <td>Sort the results of the query<br>
309
- <code>query.sort(name: -1)</code></td></tr>
310
-
311
- <tr><th>distinct</th>
312
- <td>Get the distinct values for a field.<br>
313
- <code>query.distinct(:name)</code></td></tr>
314
-
315
- <tr><th>select</th>
316
- <td>Select a set of fields to return.<br>
317
- <code>query.select(_id: 0, name: 1)</code></td></tr>
318
-
319
- <tr><th>one/first</th>
320
- <td>Return the first result from the query.<br>
321
- <code>query.one</code></td></tr>
322
-
323
- <tr><th>each</th>
324
- <td>Iterate through the results of the query.<br>
325
- <code>query.each { |doc| }</code></td></tr>
326
-
327
- <tr><th>count</th>
328
- <td>Return the number of documents matching the query.<br>
329
- <code>query.count</code></td></tr>
330
-
331
- <tr><th>update</th>
332
- <td>Update the first document matching the query's selector.<br>
333
- <code>query.update(name: "John")</code></td></tr>
334
-
335
- <tr><th>update_all</th>
336
- <td>Update all documents matching the query's selector.<br>
337
- <code>query.update_all(name: "John")</code></td></tr>
338
-
339
- <tr><th>upsert</th>
340
- <td>Create or update a document using query's selector.<br>
341
- <code>query.upsert(name: "John")</code></td></tr>
342
-
343
- <tr><th>remove</th>
344
- <td>Remove a single document matching the query's selector.<br>
345
- <code>query.remove</code></td></tr>
346
-
347
- <tr><th>remove_all</th>
348
- <td>Remove all documents matching the query's selector.<br>
349
- <code>query.remove_all</code></td></tr>
350
-
351
- </tbody></table>
352
-
353
- # Exceptions
354
-
355
- Here's a list of the exceptions generated by Moped.
356
-
357
- <table><tbody>
358
-
359
- <tr><th>Moped::Errors::ConnectionFailure</th>
360
- <td>Raised when a node cannot be reached or a connection is lost.
361
- <br>
362
- <strong>Note:</strong> this exception is only raised if Moped could not
363
- reconnect, so you shouldn't attempt to rescue this.</td></tr>
364
-
365
- <tr><th>Moped::Errors::OperationFailure</th>
366
- <td>Raised when a command fails or is invalid, such as when an insert fails in
367
- safe mode.</td></tr>
368
-
369
- <tr><th>Moped::Errors::QueryFailure</th>
370
- <td>Raised when an invalid query was sent to the database.</td></tr>
371
-
372
- <tr><th>Moped::Errors::AuthenticationFailure</th>
373
- <td>Raised when invalid credentials were passed to `session.login`.</td></tr>
374
-
375
- <tr><th>Moped::Errors::SocketError</th>
376
- <td>Not a real exception, but a module used to tag unhandled exceptions inside
377
- of a node's networking code. Allows you to `rescue Moped::SocketError` which
378
- preserving the real exception.</td></tr>
379
-
380
- </tbody></table>
381
-
382
- Other exceptions are possible while running commands, such as IO Errors around
383
- failed connections. Moped tries to be smart about managing its connections,
384
- such as checking if they're dead before executing a command; but those checks
385
- aren't foolproof, and Moped is conservative about handling unexpected errors on
386
- its connections. Namely, Moped will *not* retry a command if an unexpected
387
- exception is raised. Why? Because it's impossible to know whether the command
388
- was actually received by the remote Mongo instance, and without domain
389
- knowledge it cannot be safely retried.
390
-
391
- Take for example this case:
392
-
393
- ```ruby
394
- session.with(safe: true)["users"].insert(name: "John")
395
- ```
396
-
397
- It's entirely possible that the insert command will be sent to Mongo, but the
398
- connection gets closed before we read the result for `getLastError`. In this
399
- case, there's no way to know whether the insert was actually successful!
400
-
401
- If, however, you want to gracefully handle this in your own application, you
402
- could do something like:
403
-
404
- ```ruby
405
- document = { _id: Moped::BSON::ObjectId.new, name: "John" }
406
-
407
- begin
408
- session["users"].insert(document)
409
- rescue Moped::Errors::SocketError
410
- session["users"].find(_id: document[:_id]).upsert(document)
411
- end
412
- ```
413
-
414
- # Replica Sets
415
-
416
- Moped has full support for replica sets including automatic failover and node
417
- discovery.
418
-
419
- ## Automatic Failover
420
-
421
- Moped will automatically retry lost connections and attempt to detect dead
422
- connections before sending an operation. Note, that it will *not* retry
423
- individual operations! For example, these cases will work and not raise any
424
- exceptions:
425
-
426
- ```ruby
427
- session[:users].insert(name: "John")
428
- # kill primary node and promote secondary
429
- session[:users].insert(name: "John")
430
- session[:users].find.count # => 2.0
431
-
432
- # primary node drops our connection
433
- session[:users].insert(name: "John")
434
- ```
435
-
436
- However, you'll get an operation error in a case like:
437
-
438
- ```ruby
439
- # primary node goes down while reading the reply
440
- session.with(safe: true)[:users].insert(name: "John")
441
- ```
442
-
443
- And you'll get a connection error in a case like:
444
-
445
- ```ruby
446
- # primary node goes down, no new primary available yet
447
- session[:users].insert(name: "John")
448
- ```
449
-
450
- If your session is running with eventual consistency, read operations will
451
- never raise connection errors as long as any secondary or primary node is
452
- running. The only case where you'll see a connection failure is if a node goes
453
- down while attempting to retrieve more results from a cursor, because cursors
454
- are tied to individual nodes.
18
+ Documentation
19
+ -------------
455
20
 
456
- When two attempts to connect to a node fail, it will be marked as down. This
457
- removes it from the list of available nodes for `:down_interval` (default 30
458
- seconds). Note that the `:down_interval` only applies to normal operations;
459
- that is, if you ask for a primary node and none is available, all nodes will be
460
- retried. Likewise, if you ask for a secondary node, and no secondary or primary
461
- node is available, all nodes will be retreied.
21
+ Please see the new Mongoid website for up-to-date documentation in
22
+ the Moped section: [mongoid.org](http://mongoid.org/en/moped/)
462
23
 
463
- ## Node Discovery
24
+ License
25
+ -------
464
26
 
465
- The addresses you pass into your session are used as seeds for setting up
466
- replica set connections. After connection, each seed node will return a list of
467
- other known nodes which will be added to the set.
27
+ Copyright (c) 2011-2012 Bernerd Schaefer
468
28
 
469
- This information is cached according to the `:refresh_interval` option (default:
470
- 5 minutes). That means, e.g., that if you add a new node to your replica set,
471
- it should be represented in Moped within 5 minutes.
29
+ Permission is hereby granted, free of charge, to any person obtaining
30
+ a copy of this software and associated documentation files (the
31
+ "Software"), to deal in the Software without restriction, including
32
+ without limitation the rights to use, copy, modify, merge, publish,
33
+ distribute, sublicense, and/or sell copies of the Software, and to
34
+ permit persons to whom the Software is furnished to do so, subject to
35
+ the following conditions:
472
36
 
473
- # Thread-Safety
37
+ The above copyright notice and this permission notice shall be
38
+ included in all copies or substantial portions of the Software.
474
39
 
475
- Moped is thread-safe -- depending on your definition of thread-safe. For Moped,
476
- it means that there's no shared, global state between multiple sessions. What
477
- it doesn't mean is that a single `Session` instance can be interacted with
478
- across threads.
40
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
41
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
43
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
44
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
45
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
46
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
479
47
 
480
- Why not? Because threading is hard. Well, it's more than that -- though the
481
- public API for Moped is quite simple, MongoDB requires a good deal of
482
- complexity out of the internal API, specifically around replica sets and
483
- failover. We've decided that, for now, it's not worth making the replica set
484
- code thread-safe.
48
+ Credits
49
+ -------
485
50
 
486
- **TL;DR**: use one `Moped::Session` instance per thread.
51
+ Bernerd Schaefer bj schaefer at gmail dot com