moped 1.0.0.beta → 1.0.0.rc

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011-2012 Bernerd Schaefer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,6 +1,17 @@
1
+ Moped [![Build Status](https://secure.travis-ci.org/mongoid/moped.png?branch=master&.png)](http://travis-ci.org/mongoid/moped)
2
+ ========
3
+
1
4
  Moped is a MongoDB driver for Ruby, which exposes a simple, elegant, and fast
2
5
  API.
3
6
 
7
+ Compatibility
8
+ -------------
9
+
10
+ Moped is tested against MRI 1.9.2, 1.9.3, 2.0.0, and JRuby (1.9).
11
+
12
+ Usage
13
+ -----
14
+
4
15
  ```ruby
5
16
  session = Moped::Session.new %w[127.0.0.1:27017]
6
17
  session.use "echo_test"
@@ -473,11 +484,3 @@ failover. We've decided that, for now, it's not worth making the replica set
473
484
  code thread-safe.
474
485
 
475
486
  **TL;DR**: use one `Moped::Session` instance per thread.
476
-
477
- # Compatibility
478
-
479
- Moped is tested against MRI 1.9.2, 1.9.3, 2.0.0, and JRuby (1.9).
480
-
481
- <img src="https://secure.travis-ci.org/mongoid/moped.png?branch=master&.png"/>
482
-
483
- [Build History](http://travis-ci.org/mongoid/moped)
data/lib/moped/bson.rb CHANGED
@@ -21,5 +21,22 @@ module Moped
21
21
  FLOAT_PACK = 'E'.freeze
22
22
 
23
23
  START_LENGTH = [0].pack(INT32_PACK).freeze
24
+
25
+ class << self
26
+
27
+ # Create a new object id from the provided string.
28
+ #
29
+ # @example Create a new object id.
30
+ # Moped::BSON::ObjectId("4faf83c7dbf89b7b29000001")
31
+ #
32
+ # @param [ String ] string The string to use.
33
+ #
34
+ # @return [ ObjectId ] The object id.
35
+ #
36
+ # @since 1.0.0
37
+ def ObjectId(string)
38
+ ObjectId.from_string(string)
39
+ end
40
+ end
24
41
  end
25
42
  end
@@ -10,7 +10,7 @@ module Moped
10
10
  io.read 4
11
11
 
12
12
  while (buf = io.readbyte) != 0
13
- key = io.gets(NULL_BYTE).chop!.force_encoding('utf-8')
13
+ key = io.gets(NULL_BYTE).chop!
14
14
 
15
15
  if native_class = Types::MAP[buf]
16
16
  doc[key] = native_class.__bson_load__(io)
@@ -34,7 +34,7 @@ module Moped
34
34
  io << START_LENGTH
35
35
 
36
36
  each do |k, v|
37
- v.__bson_dump__(io, k.to_s.encode('utf-8').force_encoding('binary'))
37
+ v.__bson_dump__(io, k.to_s)
38
38
  end
39
39
  io << EOD
40
40
 
@@ -5,7 +5,7 @@ module Moped
5
5
  module Regexp
6
6
  module ClassMethods
7
7
  def __bson_load__(io)
8
- source = io.gets(NULL_BYTE).chop!.force_encoding('utf-8')
8
+ source = io.gets(NULL_BYTE).chop!
9
9
  options = 0
10
10
  while (option = io.getbyte) != 0
11
11
  case option
@@ -26,7 +26,7 @@ module Moped
26
26
  io << Types::REGEX
27
27
  io << key
28
28
  io << NULL_BYTE
29
- io << source.force_encoding('binary')
29
+ io << source
30
30
  io << NULL_BYTE
31
31
 
32
32
  io << 'i' if (options & ::Regexp::IGNORECASE) != 0
@@ -14,9 +14,19 @@ module Moped
14
14
  io << key
15
15
  io << NULL_BYTE
16
16
 
17
- str = to_s.force_encoding('utf-8').force_encoding('binary')
18
- io << [str.bytesize+1].pack(INT32_PACK)
19
- io << str
17
+ begin
18
+ data = to_s.encode('utf-8')
19
+ rescue EncodingError
20
+ data = to_s.dup
21
+ data.force_encoding('utf-8')
22
+
23
+ raise unless data.valid_encoding?
24
+ end
25
+
26
+ data.force_encoding('binary')
27
+
28
+ io << [data.bytesize+1].pack(INT32_PACK)
29
+ io << data
20
30
  io << NULL_BYTE
21
31
  end
22
32
  end
data/lib/moped/cluster.rb CHANGED
@@ -1,15 +1,37 @@
1
1
  module Moped
2
2
 
3
+ # The cluster represents a cluster of MongoDB server nodes, either a single
4
+ # node, a replica set, or a mongos server.
3
5
  class Cluster
4
6
 
5
- # @return [Array<String>] the seeds the replica set was initialized with
7
+ # @attribute [r] seeds The seeds the cluster was initialized with.
6
8
  attr_reader :seeds
7
9
 
8
- # @option options :down_interval number of seconds to wait before attempting
9
- # to reconnect to a down node. (30)
10
+ # Get the authentication details for the cluster.
11
+ #
12
+ # @example Get the authentication details.
13
+ # cluster.auth
14
+ #
15
+ # @return [ Hash ] the cached authentication credentials for this cluster.
16
+ #
17
+ # @since 1.0.0
18
+ def auth
19
+ @auth ||= {}
20
+ end
21
+
22
+ # Initialize the new cluster.
23
+ #
24
+ # @example Initialize the cluster.
25
+ # Cluster.new([ "localhost:27017" ], down_interval: 20)
10
26
  #
27
+ # @param [ Hash ] options The cluster options.
28
+ #
29
+ # @option options :down_interval number of seconds to wait before attempting
30
+ # to reconnect to a down node. (30)
11
31
  # @option options :refresh_interval number of seconds to cache information
12
- # about a node. (300)
32
+ # about a node. (300)
33
+ #
34
+ # @since 1.0.0
13
35
  def initialize(hosts, options)
14
36
  @options = {
15
37
  down_interval: 30,
@@ -20,13 +42,45 @@ module Moped
20
42
  @nodes = hosts.map { |host| Node.new(host) }
21
43
  end
22
44
 
45
+ # Returns the list of available nodes, refreshing 1) any nodes which were
46
+ # down and ready to be checked again and 2) any nodes whose information is
47
+ # out of date.
48
+ #
49
+ # @example Get the available nodes.
50
+ # cluster.nodes
51
+ #
52
+ # @return [ Array<Node> ] the list of available nodes.
53
+ #
54
+ # @since 1.0.0
55
+ def nodes
56
+ # Find the nodes that were down but are ready to be refreshed, or those
57
+ # with stale connection information.
58
+ needs_refresh, available = @nodes.partition do |node|
59
+ (node.down? && node.down_at < (Time.new - @options[:down_interval])) ||
60
+ node.needs_refresh?(Time.new - @options[:refresh_interval])
61
+ end
62
+
63
+ # Refresh those nodes.
64
+ available.concat refresh(needs_refresh)
65
+
66
+ # Now return all the nodes that are available.
67
+ available.reject(&:down?)
68
+ end
69
+
23
70
  # Refreshes information for each of the nodes provided. The node list
24
71
  # defaults to the list of all known nodes.
25
72
  #
26
73
  # If a node is successfully refreshed, any newly discovered peers will also
27
74
  # be refreshed.
28
75
  #
29
- # @return [Array<Node>] the available nodes
76
+ # @example Refresh the nodes.
77
+ # cluster.refresh
78
+ #
79
+ # @param [ Array<Node> ] nodes_to_refresh The nodes to refresh.
80
+ #
81
+ # @return [ Array<Node> ] the available nodes
82
+ #
83
+ # @since 1.0.0
30
84
  def refresh(nodes_to_refresh = @nodes)
31
85
  refreshed_nodes = []
32
86
  seen = {}
@@ -46,43 +100,34 @@ module Moped
46
100
  refreshed_nodes << node unless refreshed_nodes.include?(node)
47
101
 
48
102
  # Now refresh any newly discovered peer nodes.
49
- (node.peers - @nodes).each &refresh_node
103
+ (node.peers - @nodes).each(&refresh_node)
50
104
  rescue Errors::ConnectionFailure
51
105
  # We couldn't connect to the node, so don't do anything with it.
52
106
  end
53
107
  end
54
108
  end
55
109
 
56
- nodes_to_refresh.each &refresh_node
57
-
110
+ nodes_to_refresh.each(&refresh_node)
58
111
  refreshed_nodes.to_a
59
112
  end
60
113
 
61
- # Returns the list of available nodes, refreshing 1) any nodes which were
62
- # down and ready to be checked again and 2) any nodes whose information is
63
- # out of date.
64
- #
65
- # @return [Array<Node>] the list of available nodes.
66
- def nodes
67
- # Find the nodes that were down but are ready to be refreshed, or those
68
- # with stale connection information.
69
- needs_refresh, available = @nodes.partition do |node|
70
- (node.down? && node.down_at < (Time.new - @options[:down_interval])) ||
71
- node.needs_refresh?(Time.new - @options[:refresh_interval])
72
- end
73
-
74
- # Refresh those nodes.
75
- available.concat refresh(needs_refresh)
76
-
77
- # Now return all the nodes that are available.
78
- available.reject &:down?
79
- end
80
-
81
114
  # Yields the replica set's primary node to the provided block. This method
82
115
  # will retry the block in case of connection errors or replica set
83
116
  # reconfiguration.
84
117
  #
85
- # @raises ConnectionFailure when no primary node can be found
118
+ # @example Yield the primary to the block.
119
+ # cluster.with_primary do |node|
120
+ # # ...
121
+ # end
122
+ #
123
+ # @param [ true, false ] retry_on_failure Whether to retry if an error was
124
+ # raised.
125
+ #
126
+ # @raises [ ConnectionFailure ] When no primary node can be found
127
+ #
128
+ # @return [ Object ] The result of the yield.
129
+ #
130
+ # @since 1.0.0
86
131
  def with_primary(retry_on_failure = true, &block)
87
132
  if node = nodes.find(&:primary?)
88
133
  begin
@@ -100,14 +145,29 @@ module Moped
100
145
  refresh
101
146
  with_primary(false, &block)
102
147
  else
103
- raise Errors::ConnectionFailure, "Could not connect to a primary node for replica set #{inspect}"
148
+ raise(
149
+ Errors::ConnectionFailure,
150
+ "Could not connect to a primary node for replica set #{inspect}"
151
+ )
104
152
  end
105
153
  end
106
154
 
107
155
  # Yields a secondary node if available, otherwise the primary node. This
108
156
  # method will retry the block in case of connection errors.
109
157
  #
110
- # @raises ConnectionError when no secondary or primary node can be found
158
+ # @example Yield the secondary to the block.
159
+ # cluster.with_secondary do |node|
160
+ # # ...
161
+ # end
162
+ #
163
+ # @param [ true, false ] retry_on_failure Whether to retry if an error was
164
+ # raised.
165
+ #
166
+ # @raises [ ConnectionFailure ] When no primary node can be found
167
+ #
168
+ # @return [ Object ] The result of the yield.
169
+ #
170
+ # @since 1.0.0
111
171
  def with_secondary(retry_on_failure = true, &block)
112
172
  available_nodes = nodes.shuffle!.partition(&:secondary?).flatten
113
173
 
@@ -126,20 +186,17 @@ module Moped
126
186
  refresh
127
187
  with_secondary(false, &block)
128
188
  else
129
- raise Errors::ConnectionFailure, "Could not connect to any secondary or primary nodes for replica set #{inspect}"
189
+ raise(
190
+ Errors::ConnectionFailure,
191
+ "Could not connect to any secondary or primary nodes for replica set #{inspect}"
192
+ )
130
193
  end
131
194
  end
132
195
 
133
- # @return [Hash] the cached authentication credentials for this cluster.
134
- def auth
135
- @auth ||= {}
136
- end
137
-
138
196
  private
139
197
 
140
198
  def initialize_copy(_)
141
- @nodes = @nodes.map &:dup
199
+ @nodes = @nodes.map(&:dup)
142
200
  end
143
-
144
201
  end
145
202
  end
@@ -9,54 +9,77 @@ module Moped
9
9
  # users.find.to_a # => [{ name: "John" }]
10
10
  class Collection
11
11
 
12
- # @return [Database] the database this collection belongs to
13
- attr_reader :database
12
+ # @attribute [r] database The collection's database.
13
+ # @attribute [r] name The collection name.
14
+ attr_reader :database, :name
14
15
 
15
- # @return [String, Symbol] the collection's name
16
- attr_reader :name
16
+ # Drop the collection.
17
+ #
18
+ # @example Drop the collection.
19
+ # collection.drop
20
+ #
21
+ # @return [ Hash ] The command information.
22
+ #
23
+ # @since 1.0.0
24
+ def drop
25
+ database.command(drop: name)
26
+ end
17
27
 
18
- # @param [Database] database the database this collection belongs to
19
- # @param [String, Symbol] name the collection's name
20
- def initialize(database, name)
21
- @database = database
22
- @name = name
28
+ # Build a query for this collection.
29
+ #
30
+ # @example Build a query based on the provided selector.
31
+ # collection.find(name: "Placebo")
32
+ #
33
+ # @param [ Hash ] selector The query selector.
34
+ #
35
+ # @return [ Query ] The generated query.
36
+ #
37
+ # @since 1.0.0
38
+ def find(selector = {})
39
+ Query.new(self, selector)
23
40
  end
41
+ alias :where :find
24
42
 
25
43
  # Access information about this collection's indexes.
26
44
  #
27
- # @return [Indexes]
45
+ # @example Get the index information.
46
+ # collection.indexes
47
+ #
48
+ # @return [ Indexes ] The index information.
49
+ #
50
+ # @since 1.0.0
28
51
  def indexes
29
52
  Indexes.new(database, name)
30
53
  end
31
54
 
32
- # Drop the collection.
33
- def drop
34
- database.command drop: name
35
- end
36
-
37
- # Build a query for this collection.
55
+ # Initialize the new collection.
38
56
  #
39
- # @param [Hash] selector the selector
40
- # @return [Moped::Query]
41
- def find(selector = {})
42
- Query.new self, selector
57
+ # @example Initialize the collection.
58
+ # Collection.new(database, :artists)
59
+ #
60
+ # @param [ Database ] database The collection's database.
61
+ # @param [ String, Symbol] name The collection name.
62
+ #
63
+ # @since 1.0.0
64
+ def initialize(database, name)
65
+ @database, @name = database, name
43
66
  end
44
- alias where find
45
67
 
46
68
  # Insert one or more documents into the collection.
47
69
  #
48
- # @overload insert(document)
49
- # @example
50
- # db[:people].insert(name: "John")
51
- # @param [Hash] document the document to insert
70
+ # @example Insert a single document.
71
+ # db[:people].insert(name: "John")
72
+ #
73
+ # @example Insert multiple documents in batch.
74
+ # db[:people].insert([{name: "John"}, {name: "Joe"}])
52
75
  #
53
- # @overload insert(documents)
54
- # @example
55
- # db[:people].insert([{name: "John"}, {name: "Joe"}])
56
- # @param [Array<Hash>] documents the documents to insert
76
+ # @param [ Hash, Array<Hash> ] documents The document(s) to insert.
77
+ #
78
+ # @return [ nil ] nil.
79
+ #
80
+ # @since 1.0.0
57
81
  def insert(documents)
58
- documents = [documents] unless documents.is_a? Array
59
-
82
+ documents = [documents] unless documents.is_a?(Array)
60
83
  database.session.with(consistency: :strong) do |session|
61
84
  session.context.insert(database.name, name, documents)
62
85
  end