moped 1.5.3 → 2.0.0.beta
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -5
- data/README.md +1 -1
- data/lib/moped.rb +10 -13
- data/lib/moped/address.rb +56 -0
- data/lib/moped/authenticatable.rb +89 -0
- data/lib/moped/cluster.rb +169 -136
- data/lib/moped/collection.rb +53 -19
- data/lib/moped/connection.rb +69 -10
- data/lib/moped/connection/manager.rb +49 -0
- data/lib/moped/connection/pool.rb +198 -0
- data/lib/moped/connection/queue.rb +93 -0
- data/lib/moped/connection/reaper.rb +52 -0
- data/lib/moped/connection/socket.rb +4 -0
- data/lib/moped/connection/socket/connectable.rb +169 -0
- data/lib/moped/connection/socket/ssl.rb +52 -0
- data/lib/moped/connection/socket/tcp.rb +25 -0
- data/lib/moped/connection/sockets.rb +4 -0
- data/lib/moped/cursor.rb +3 -5
- data/lib/moped/database.rb +18 -24
- data/lib/moped/errors.rb +35 -6
- data/lib/moped/executable.rb +96 -0
- data/lib/moped/failover.rb +41 -0
- data/lib/moped/failover/disconnect.rb +31 -0
- data/lib/moped/failover/ignore.rb +29 -0
- data/lib/moped/failover/reconfigure.rb +34 -0
- data/lib/moped/failover/retry.rb +37 -0
- data/lib/moped/indexes.rb +4 -1
- data/lib/moped/instrumentable.rb +39 -0
- data/lib/moped/instrumentable/log.rb +43 -0
- data/lib/moped/instrumentable/noop.rb +31 -0
- data/lib/moped/loggable.rb +110 -0
- data/lib/moped/node.rb +316 -297
- data/lib/moped/operation.rb +3 -0
- data/lib/moped/operation/read.rb +62 -0
- data/lib/moped/operation/write.rb +57 -0
- data/lib/moped/protocol/command.rb +65 -4
- data/lib/moped/protocol/commands/authenticate.rb +1 -2
- data/lib/moped/protocol/delete.rb +16 -0
- data/lib/moped/protocol/get_more.rb +102 -31
- data/lib/moped/protocol/insert.rb +17 -0
- data/lib/moped/protocol/message.rb +44 -46
- data/lib/moped/protocol/query.rb +175 -92
- data/lib/moped/protocol/reply.rb +19 -8
- data/lib/moped/protocol/update.rb +18 -0
- data/lib/moped/query.rb +43 -17
- data/lib/moped/read_preference.rb +49 -0
- data/lib/moped/read_preference/nearest.rb +55 -0
- data/lib/moped/read_preference/primary.rb +60 -0
- data/lib/moped/read_preference/primary_preferred.rb +55 -0
- data/lib/moped/read_preference/secondary.rb +50 -0
- data/lib/moped/read_preference/secondary_preferred.rb +53 -0
- data/lib/moped/read_preference/selectable.rb +79 -0
- data/lib/moped/readable.rb +55 -0
- data/lib/moped/session.rb +122 -70
- data/lib/moped/{mongo_uri.rb → uri.rb} +75 -31
- data/lib/moped/version.rb +1 -1
- data/lib/moped/write_concern.rb +33 -0
- data/lib/moped/write_concern/propagate.rb +38 -0
- data/lib/moped/write_concern/unverified.rb +28 -0
- metadata +79 -44
- data/lib/moped/bson.rb +0 -45
- data/lib/moped/bson/binary.rb +0 -137
- data/lib/moped/bson/code.rb +0 -112
- data/lib/moped/bson/document.rb +0 -41
- data/lib/moped/bson/extensions.rb +0 -91
- data/lib/moped/bson/extensions/array.rb +0 -37
- data/lib/moped/bson/extensions/boolean.rb +0 -16
- data/lib/moped/bson/extensions/false_class.rb +0 -19
- data/lib/moped/bson/extensions/float.rb +0 -22
- data/lib/moped/bson/extensions/hash.rb +0 -39
- data/lib/moped/bson/extensions/integer.rb +0 -36
- data/lib/moped/bson/extensions/nil_class.rb +0 -19
- data/lib/moped/bson/extensions/object.rb +0 -11
- data/lib/moped/bson/extensions/regexp.rb +0 -38
- data/lib/moped/bson/extensions/string.rb +0 -45
- data/lib/moped/bson/extensions/symbol.rb +0 -33
- data/lib/moped/bson/extensions/time.rb +0 -23
- data/lib/moped/bson/extensions/true_class.rb +0 -19
- data/lib/moped/bson/max_key.rb +0 -51
- data/lib/moped/bson/min_key.rb +0 -51
- data/lib/moped/bson/object_id.rb +0 -301
- data/lib/moped/bson/timestamp.rb +0 -38
- data/lib/moped/bson/types.rb +0 -67
- data/lib/moped/logging.rb +0 -58
- data/lib/moped/session/context.rb +0 -115
- data/lib/moped/sockets/connectable.rb +0 -167
- data/lib/moped/sockets/ssl.rb +0 -50
- data/lib/moped/sockets/tcp.rb +0 -23
- data/lib/moped/threaded.rb +0 -69
@@ -35,6 +35,43 @@ module Moped
|
|
35
35
|
#
|
36
36
|
module Message
|
37
37
|
|
38
|
+
# Default implementation for a message is to do nothing when receiving
|
39
|
+
# replies.
|
40
|
+
#
|
41
|
+
# @example Receive replies.
|
42
|
+
# message.receive_replies(connection)
|
43
|
+
#
|
44
|
+
# @param [ Connection ] connection The connection.
|
45
|
+
#
|
46
|
+
# @return [ nil ] nil.
|
47
|
+
#
|
48
|
+
# @since 1.0.0
|
49
|
+
def receive_replies(connection); end
|
50
|
+
|
51
|
+
# Serializes the message and all of its fields to a new buffer or to the
|
52
|
+
# provided buffer.
|
53
|
+
#
|
54
|
+
# @example Serliaze the message.
|
55
|
+
# message.serialize
|
56
|
+
#
|
57
|
+
# @param [ String ] buffer A buffer to serialize to.
|
58
|
+
#
|
59
|
+
# @return [ String ] The result of serliazing this message
|
60
|
+
#
|
61
|
+
# @since 1.0.0
|
62
|
+
def serialize(buffer = "")
|
63
|
+
raise NotImplementedError, "This method is generated after calling #finalize on a message class"
|
64
|
+
end
|
65
|
+
alias :to_s :serialize
|
66
|
+
|
67
|
+
# @return [String] the nicely formatted version of the message
|
68
|
+
def inspect
|
69
|
+
fields = self.class.fields.map do |field|
|
70
|
+
"@#{field}=" + __send__(field).inspect
|
71
|
+
end
|
72
|
+
"#<#{self.class.name}\n" <<
|
73
|
+
" #{fields * "\n "}>"
|
74
|
+
end
|
38
75
|
class << self
|
39
76
|
|
40
77
|
# Extends the including class with +ClassMethods+.
|
@@ -42,10 +79,8 @@ module Moped
|
|
42
79
|
# @param [Class] subclass the inheriting class
|
43
80
|
def included(base)
|
44
81
|
super
|
45
|
-
|
46
|
-
base.extend ClassMethods
|
82
|
+
base.extend(ClassMethods)
|
47
83
|
end
|
48
|
-
|
49
84
|
private :included
|
50
85
|
end
|
51
86
|
|
@@ -119,21 +154,21 @@ module Moped
|
|
119
154
|
if options[:optional]
|
120
155
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
121
156
|
def serialize_#{name}(buffer)
|
122
|
-
|
157
|
+
buffer << #{name}.to_bson if #{name}
|
123
158
|
end
|
124
159
|
RUBY
|
125
160
|
elsif options[:type] == :array
|
126
161
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
127
162
|
def serialize_#{name}(buffer)
|
128
163
|
#{name}.each do |document|
|
129
|
-
|
164
|
+
buffer << document.to_bson
|
130
165
|
end
|
131
166
|
end
|
132
167
|
RUBY
|
133
168
|
else
|
134
169
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
135
170
|
def serialize_#{name}(buffer)
|
136
|
-
|
171
|
+
buffer << #{name}.to_bson
|
137
172
|
end
|
138
173
|
RUBY
|
139
174
|
end
|
@@ -277,14 +312,12 @@ module Moped
|
|
277
312
|
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
278
313
|
def serialize(buffer = "")
|
279
314
|
start = buffer.bytesize
|
280
|
-
|
281
315
|
#{fields.map { |f| "serialize_#{f}(buffer)" }.join("\n")}
|
282
|
-
|
283
316
|
self.length = buffer.bytesize - start
|
284
|
-
buffer[start, 4] = serialize_length
|
317
|
+
buffer[start, 4] = serialize_length("")
|
285
318
|
buffer
|
286
319
|
end
|
287
|
-
alias to_s serialize
|
320
|
+
alias :to_s :serialize
|
288
321
|
EOS
|
289
322
|
end
|
290
323
|
|
@@ -294,44 +327,9 @@ module Moped
|
|
294
327
|
# identical fields.
|
295
328
|
def inherited(subclass)
|
296
329
|
super
|
297
|
-
|
298
|
-
subclass.fields.replace fields
|
299
|
-
end
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
# Default implementation for a message is to do nothing when receiving
|
304
|
-
# replies.
|
305
|
-
#
|
306
|
-
# @example Receive replies.
|
307
|
-
# message.receive_replies(connection)
|
308
|
-
#
|
309
|
-
# @param [ Connection ] connection The connection.
|
310
|
-
#
|
311
|
-
# @since 1.0.0
|
312
|
-
#
|
313
|
-
# @return [ nil ] nil.
|
314
|
-
def receive_replies(connection); end
|
315
|
-
|
316
|
-
# Serializes the message and all of its fields to a new buffer or to the
|
317
|
-
# provided buffer.
|
318
|
-
#
|
319
|
-
# @param [String] buffer a buffer to serialize to
|
320
|
-
# @return [String] the result of serliazing this message
|
321
|
-
def serialize(buffer = "")
|
322
|
-
raise NotImplementedError, "This method is generated after calling #finalize on a message class"
|
323
|
-
end
|
324
|
-
alias to_s serialize
|
325
|
-
|
326
|
-
# @return [String] the nicely formatted version of the message
|
327
|
-
def inspect
|
328
|
-
fields = self.class.fields.map do |field|
|
329
|
-
"@#{field}=" + __send__(field).inspect
|
330
|
+
subclass.fields.replace(fields)
|
330
331
|
end
|
331
|
-
"#<#{self.class.name}\n" <<
|
332
|
-
" #{fields * "\n "}>"
|
333
332
|
end
|
334
|
-
|
335
333
|
end
|
336
334
|
end
|
337
335
|
end
|
data/lib/moped/protocol/query.rb
CHANGED
@@ -1,123 +1,174 @@
|
|
1
1
|
module Moped
|
2
2
|
module Protocol
|
3
|
+
|
3
4
|
# The Protocol class for querying a collection.
|
4
5
|
#
|
5
|
-
# @
|
6
|
-
# Query.new "moped", "users", { name: "John" }
|
7
|
-
#
|
8
|
-
# @example Find all users named John skipping 5 and returning 10
|
9
|
-
# Query.new "moped", "users", { name: "John" },
|
10
|
-
# skip: 5, limit: 10
|
11
|
-
#
|
12
|
-
# @example Find all users on slave node
|
13
|
-
# Query.new "moped", "users", {}, flags: [:slave_ok]
|
14
|
-
#
|
15
|
-
# @example Find all user ids
|
16
|
-
# Query.new "moped", "users", {}, fields: { _id: 1 }
|
17
|
-
#
|
6
|
+
# @since 1.0.0
|
18
7
|
class Query
|
19
8
|
include Message
|
20
9
|
|
21
|
-
#
|
22
|
-
#
|
10
|
+
# @!attribute length
|
11
|
+
# @return [ Integer ] the length of the message
|
23
12
|
int32 :length
|
24
13
|
|
25
|
-
#
|
26
|
-
#
|
14
|
+
# @!attribute request_id
|
15
|
+
# @return [ Integer ] the request id of the message
|
27
16
|
int32 :request_id
|
28
17
|
|
29
18
|
int32 :response_to
|
30
19
|
|
31
|
-
#
|
32
|
-
#
|
20
|
+
# @!attribute op_code
|
21
|
+
# @return [ Integer ] the operation code of this message
|
33
22
|
int32 :op_code
|
34
23
|
|
35
|
-
#
|
24
|
+
# @!attribute
|
36
25
|
# The flags for the query. Supported flags are: +:tailable+, +:slave_ok+,
|
37
26
|
# +:no_cursor_timeout+, +:await_data+, +:exhaust+.
|
38
27
|
#
|
39
|
-
# @param [Array] flags the flags for this message
|
40
|
-
# @return [Array] the flags for this message
|
41
|
-
flags
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
#
|
49
|
-
cstring
|
50
|
-
|
51
|
-
#
|
52
|
-
#
|
53
|
-
int32
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
57
|
-
int32
|
58
|
-
|
59
|
-
#
|
60
|
-
#
|
28
|
+
# @param [ Array ] flags the flags for this message
|
29
|
+
# @return [ Array ] the flags for this message
|
30
|
+
flags :flags, tailable: 2 ** 1,
|
31
|
+
slave_ok: 2 ** 2,
|
32
|
+
no_cursor_timeout: 2 ** 4,
|
33
|
+
await_data: 2 ** 5,
|
34
|
+
exhaust: 2 ** 6
|
35
|
+
|
36
|
+
# @!attribute full_collection_name
|
37
|
+
# @return [ String ] the namespaced collection name
|
38
|
+
cstring :full_collection_name
|
39
|
+
|
40
|
+
# @!attribute skip
|
41
|
+
# @return [ Integer ] the number of documents to skip
|
42
|
+
int32 :skip
|
43
|
+
|
44
|
+
# @!attribute limit
|
45
|
+
# @return [ Integer ] the number of documents to return
|
46
|
+
int32 :limit
|
47
|
+
|
48
|
+
# @!attribute selector
|
49
|
+
# @return [ Hash ] the selector for this query
|
61
50
|
document :selector
|
62
51
|
|
63
|
-
#
|
64
|
-
#
|
52
|
+
# @!attribute fields
|
53
|
+
# @return [ Hash, nil ] the fields to include in the reply
|
65
54
|
document :fields, :optional => true
|
66
55
|
|
67
56
|
finalize
|
68
57
|
|
69
|
-
|
70
|
-
#
|
71
|
-
|
72
|
-
|
73
|
-
|
58
|
+
# @!attribute collection
|
59
|
+
# @return [ String ] The collection to query.
|
60
|
+
# @!attribute database
|
61
|
+
# @return [ String ] The database to query
|
62
|
+
attr_reader :collection, :database
|
74
63
|
|
75
|
-
#
|
76
|
-
|
64
|
+
# @!attribute batch_size
|
65
|
+
# @return [ Integer ] The batch size of the results.
|
66
|
+
attr_accessor :batch_size
|
77
67
|
|
78
|
-
#
|
79
|
-
|
68
|
+
# Get the basic selector.
|
69
|
+
#
|
70
|
+
# @example Get the basic selector.
|
71
|
+
# query.basic_selector
|
72
|
+
#
|
73
|
+
# @note Sometimes, like in cases of deletion we need this since MongoDB
|
74
|
+
# does not understand $query in operations like DELETE.
|
75
|
+
#
|
76
|
+
# @return [ Hash ] The basic selector.
|
77
|
+
#
|
78
|
+
# @since 2.0.0
|
79
|
+
def basic_selector
|
80
|
+
selector["$query"] || selector
|
81
|
+
end
|
80
82
|
|
81
|
-
|
83
|
+
# Get the exception specific to a failure of this particular operation.
|
84
|
+
#
|
85
|
+
# @example Get the failure exception.
|
86
|
+
# query.failure_exception(document)
|
87
|
+
#
|
88
|
+
# @param [ Moped::Protocol::Reply ] reply The reply from the database.
|
89
|
+
#
|
90
|
+
# @return [ Moped::Errors::QueryFailure ] The failure exception.
|
91
|
+
#
|
92
|
+
# @since 2.0.0
|
93
|
+
def failure_exception(reply)
|
94
|
+
Errors::QueryFailure.new(self, reply.documents.first)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Determine if the provided reply message is a failure with respect to a
|
98
|
+
# query.
|
99
|
+
#
|
100
|
+
# @example Is the reply a query failure?
|
101
|
+
# query.failure?(reply)
|
102
|
+
#
|
103
|
+
# @param [ Reply ] reply The reply to the query.
|
104
|
+
#
|
105
|
+
# @return [ true, false ] If the reply is a failure.
|
106
|
+
#
|
107
|
+
# @since 2.0.0
|
108
|
+
def failure?(reply)
|
109
|
+
reply.query_failure?
|
110
|
+
end
|
82
111
|
|
112
|
+
# Set the option on the query to not timeout the cursor.
|
113
|
+
#
|
114
|
+
# @example Set the no timeout option.
|
115
|
+
# query.no_timeout = true
|
116
|
+
#
|
117
|
+
# @param [ true, false ] enable Whether to enable the no timeout option.
|
118
|
+
#
|
119
|
+
# @since 1.3.0
|
83
120
|
def no_timeout=(enable)
|
84
121
|
@flags |= [:no_cursor_timeout] if enable
|
85
122
|
end
|
86
123
|
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# @example
|
90
|
-
# Query.new
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
# @
|
99
|
-
#
|
100
|
-
#
|
101
|
-
# @
|
102
|
-
# @
|
103
|
-
# @
|
104
|
-
# @
|
105
|
-
#
|
106
|
-
#
|
124
|
+
# Instantiate a new query operation.
|
125
|
+
#
|
126
|
+
# @example Find all users named John.
|
127
|
+
# Query.new("moped", "users", { name: "John" })
|
128
|
+
#
|
129
|
+
# @example Find all users named John skipping 5 and returning 10.
|
130
|
+
# Query.new("moped", "users", { name: "John" }, skip: 5, limit: 10)
|
131
|
+
#
|
132
|
+
# @example Find all users on slave node.
|
133
|
+
# Query.new("moped", "users", {}, flags: [ :slave_ok ])
|
134
|
+
#
|
135
|
+
# @example Find all user ids.
|
136
|
+
# Query.new("moped", "users", {}, fields: { _id: 1 })
|
137
|
+
#
|
138
|
+
# @param [ String, Symbol ] database The database to query.
|
139
|
+
# @param [ String, Symbol ] collection The collection to query.
|
140
|
+
# @param [ Hash ] selector The query selector.
|
141
|
+
# @param [ Hash ] options The additional query options.
|
142
|
+
#
|
143
|
+
# @option options [ Integer ] :request_id The operation's request id.
|
144
|
+
# @option options [ Integer ] :skip The number of documents to skip.
|
145
|
+
# @option options [ Integer ] :limit The number of documents to return.
|
146
|
+
# @option options [ Hash ] :fields The limited fields to return.
|
147
|
+
# @option options [ Array ] :flags The flags for querying. Supported flags
|
148
|
+
# are: :tailable, :slave_ok, :no_cursor_timeout, :await_data, :exhaust.
|
149
|
+
#
|
150
|
+
# @since 1.0.0
|
107
151
|
def initialize(database, collection, selector, options = {})
|
108
152
|
@database = database
|
109
153
|
@collection = collection
|
110
|
-
|
111
154
|
@full_collection_name = "#{database}.#{collection}"
|
112
|
-
@selector
|
113
|
-
@request_id
|
114
|
-
@flags
|
115
|
-
@limit
|
116
|
-
@skip
|
117
|
-
@fields
|
118
|
-
@batch_size
|
155
|
+
@selector = selector
|
156
|
+
@request_id = options[:request_id]
|
157
|
+
@flags = options[:flags] || []
|
158
|
+
@limit = options[:limit]
|
159
|
+
@skip = options[:skip]
|
160
|
+
@fields = options[:fields]
|
161
|
+
@batch_size = options[:batch_size]
|
119
162
|
end
|
120
163
|
|
164
|
+
# Provide the value that will be logged when the query runs.
|
165
|
+
#
|
166
|
+
# @example Provide the log inspection.
|
167
|
+
# query.log_inspect
|
168
|
+
#
|
169
|
+
# @return [ String ] The string value for logging.
|
170
|
+
#
|
171
|
+
# @since 1.0.0
|
121
172
|
def log_inspect
|
122
173
|
type = "QUERY"
|
123
174
|
fields = []
|
@@ -134,19 +185,18 @@ module Moped
|
|
134
185
|
f.join(" ") % v
|
135
186
|
end
|
136
187
|
|
137
|
-
|
138
|
-
|
139
|
-
#
|
140
|
-
# query.basic_selector
|
188
|
+
undef op_code
|
189
|
+
|
190
|
+
# Get the code for a query operation.
|
141
191
|
#
|
142
|
-
# @
|
143
|
-
#
|
192
|
+
# @example Get the operation code.
|
193
|
+
# query.op_code
|
144
194
|
#
|
145
|
-
# @return [
|
195
|
+
# @return [ Integer ] OP_QUERY operation code (2004).
|
146
196
|
#
|
147
|
-
# @since
|
148
|
-
def
|
149
|
-
|
197
|
+
# @since 1.0.0
|
198
|
+
def op_code
|
199
|
+
2004
|
150
200
|
end
|
151
201
|
|
152
202
|
# Receive replies to the message.
|
@@ -162,6 +212,39 @@ module Moped
|
|
162
212
|
def receive_replies(connection)
|
163
213
|
connection.read
|
164
214
|
end
|
215
|
+
|
216
|
+
# Take the provided reply and return the expected results to api
|
217
|
+
# consumers.
|
218
|
+
#
|
219
|
+
# @example Get the expected results of the reply.
|
220
|
+
# query.results(reply)
|
221
|
+
#
|
222
|
+
# @param [ Moped::Protocol::Reply ] reply The reply from the database.
|
223
|
+
#
|
224
|
+
# @return [ Moped::Protocol::Reply ] The reply.
|
225
|
+
#
|
226
|
+
# @since 2.0.0
|
227
|
+
def results(reply)
|
228
|
+
reply
|
229
|
+
end
|
230
|
+
|
231
|
+
private
|
232
|
+
|
233
|
+
# Duplicate the attributes in the query that need to be.
|
234
|
+
#
|
235
|
+
# @api private
|
236
|
+
#
|
237
|
+
# @example Clone the query.
|
238
|
+
# query.clone
|
239
|
+
#
|
240
|
+
# @param [ Query ] The query that was cloned from.
|
241
|
+
#
|
242
|
+
# @since 2.0.0
|
243
|
+
def initialize_copy(_)
|
244
|
+
@selector = selector.dup
|
245
|
+
@flags = flags.dup
|
246
|
+
@fields = fields.dup if fields
|
247
|
+
end
|
165
248
|
end
|
166
249
|
end
|
167
250
|
end
|