mongo 2.4.3 → 2.5.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -2
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +3 -2
  5. data/lib/mongo/auth/cr.rb +6 -4
  6. data/lib/mongo/auth/cr/conversation.rb +33 -17
  7. data/lib/mongo/auth/ldap.rb +4 -2
  8. data/lib/mongo/auth/ldap/conversation.rb +19 -9
  9. data/lib/mongo/auth/scram.rb +7 -4
  10. data/lib/mongo/auth/scram/conversation.rb +62 -24
  11. data/lib/mongo/auth/user.rb +10 -0
  12. data/lib/mongo/auth/user/view.rb +44 -22
  13. data/lib/mongo/auth/x509.rb +4 -2
  14. data/lib/mongo/auth/x509/conversation.rb +19 -9
  15. data/lib/mongo/bulk_write.rb +33 -27
  16. data/lib/mongo/bulk_write/combineable.rb +5 -0
  17. data/lib/mongo/bulk_write/transformable.rb +2 -0
  18. data/lib/mongo/bulk_write/validatable.rb +4 -0
  19. data/lib/mongo/client.rb +123 -12
  20. data/lib/mongo/cluster.rb +52 -11
  21. data/lib/mongo/cluster/app_metadata.rb +8 -2
  22. data/lib/mongo/cluster/cursor_reaper.rb +0 -1
  23. data/lib/mongo/cluster/topology.rb +1 -1
  24. data/lib/mongo/collection.rb +114 -27
  25. data/lib/mongo/collection/view.rb +8 -2
  26. data/lib/mongo/collection/view/aggregation.rb +11 -7
  27. data/lib/mongo/collection/view/builder/aggregation.rb +5 -1
  28. data/lib/mongo/collection/view/builder/find_command.rb +5 -3
  29. data/lib/mongo/collection/view/builder/map_reduce.rb +11 -3
  30. data/lib/mongo/collection/view/builder/op_query.rb +1 -1
  31. data/lib/mongo/collection/view/change_stream.rb +160 -0
  32. data/lib/mongo/collection/view/change_stream/retryable.rb +57 -0
  33. data/lib/mongo/collection/view/iterable.rb +11 -10
  34. data/lib/mongo/collection/view/map_reduce.rb +22 -18
  35. data/lib/mongo/collection/view/readable.rb +51 -37
  36. data/lib/mongo/collection/view/writable.rb +72 -40
  37. data/lib/mongo/cursor.rb +25 -4
  38. data/lib/mongo/cursor/builder/get_more_command.rb +4 -2
  39. data/lib/mongo/database.rb +22 -11
  40. data/lib/mongo/database/view.rb +16 -12
  41. data/lib/mongo/error.rb +5 -0
  42. data/lib/mongo/error/invalid_session.rb +36 -0
  43. data/lib/mongo/error/missing_resume_token.rb +39 -0
  44. data/lib/mongo/error/operation_failure.rb +17 -0
  45. data/lib/mongo/error/parser.rb +3 -2
  46. data/lib/mongo/error/unknown_payload_type.rb +41 -0
  47. data/lib/mongo/error/unsupported_array_filters.rb +51 -0
  48. data/lib/mongo/error/unsupported_message_type.rb +23 -0
  49. data/lib/mongo/grid/fs_bucket.rb +5 -4
  50. data/lib/mongo/grid/stream/read.rb +3 -2
  51. data/lib/mongo/grid/stream/write.rb +2 -2
  52. data/lib/mongo/index/view.rb +35 -25
  53. data/lib/mongo/monitoring/event/secure.rb +14 -0
  54. data/lib/mongo/operation.rb +16 -0
  55. data/lib/mongo/operation/commands.rb +1 -0
  56. data/lib/mongo/operation/commands/aggregate.rb +9 -5
  57. data/lib/mongo/operation/commands/aggregate/result.rb +1 -1
  58. data/lib/mongo/operation/commands/collections_info.rb +6 -6
  59. data/lib/mongo/operation/commands/command.rb +2 -1
  60. data/lib/mongo/operation/commands/create.rb +6 -2
  61. data/lib/mongo/operation/commands/drop.rb +6 -2
  62. data/lib/mongo/operation/commands/drop_database.rb +6 -2
  63. data/lib/mongo/operation/commands/explain.rb +27 -0
  64. data/lib/mongo/operation/commands/explain/result.rb +52 -0
  65. data/lib/mongo/operation/commands/indexes.rb +1 -1
  66. data/lib/mongo/operation/commands/list_collections.rb +1 -1
  67. data/lib/mongo/operation/commands/list_collections/result.rb +1 -1
  68. data/lib/mongo/operation/commands/list_indexes.rb +1 -1
  69. data/lib/mongo/operation/commands/list_indexes/result.rb +1 -1
  70. data/lib/mongo/operation/commands/map_reduce.rb +8 -4
  71. data/lib/mongo/operation/commands/map_reduce/result.rb +13 -1
  72. data/lib/mongo/operation/commands/user_query.rb +1 -1
  73. data/lib/mongo/operation/commands/users_info.rb +6 -2
  74. data/lib/mongo/operation/executable.rb +4 -1
  75. data/lib/mongo/operation/read_preference.rb +10 -5
  76. data/lib/mongo/operation/result.rb +26 -2
  77. data/lib/mongo/operation/specifiable.rb +13 -1
  78. data/lib/mongo/operation/uses_command_op_msg.rb +47 -0
  79. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -1
  80. data/lib/mongo/operation/write/bulk/insert/result.rb +4 -4
  81. data/lib/mongo/operation/write/command/create_index.rb +6 -1
  82. data/lib/mongo/operation/write/command/delete.rb +28 -4
  83. data/lib/mongo/operation/write/command/drop_index.rb +6 -1
  84. data/lib/mongo/operation/write/command/insert.rb +22 -18
  85. data/lib/mongo/operation/write/command/update.rb +24 -9
  86. data/lib/mongo/operation/write/command/writable.rb +14 -1
  87. data/lib/mongo/operation/write/insert.rb +4 -1
  88. data/lib/mongo/operation/write/insert/result.rb +2 -2
  89. data/lib/mongo/operation/write/update.rb +7 -1
  90. data/lib/mongo/operation/write/write_command_enabled.rb +20 -3
  91. data/lib/mongo/protocol.rb +3 -0
  92. data/lib/mongo/protocol/bit_vector.rb +2 -2
  93. data/lib/mongo/protocol/compressed.rb +135 -0
  94. data/lib/mongo/protocol/delete.rb +8 -6
  95. data/lib/mongo/protocol/get_more.rb +8 -6
  96. data/lib/mongo/protocol/insert.rb +8 -6
  97. data/lib/mongo/protocol/kill_cursors.rb +8 -6
  98. data/lib/mongo/protocol/message.rb +31 -3
  99. data/lib/mongo/protocol/msg.rb +172 -0
  100. data/lib/mongo/protocol/query.rb +26 -6
  101. data/lib/mongo/protocol/registry.rb +76 -0
  102. data/lib/mongo/protocol/reply.rb +10 -5
  103. data/lib/mongo/protocol/serializers.rb +224 -0
  104. data/lib/mongo/protocol/update.rb +8 -6
  105. data/lib/mongo/retryable.rb +4 -2
  106. data/lib/mongo/server.rb +6 -3
  107. data/lib/mongo/server/connectable.rb +1 -1
  108. data/lib/mongo/server/connection.rb +30 -8
  109. data/lib/mongo/server/description.rb +25 -1
  110. data/lib/mongo/server/description/features.rb +4 -1
  111. data/lib/mongo/server/monitor.rb +5 -0
  112. data/lib/mongo/server/monitor/connection.rb +50 -2
  113. data/lib/mongo/server_selector/nearest.rb +10 -4
  114. data/lib/mongo/server_selector/primary.rb +20 -0
  115. data/lib/mongo/server_selector/primary_preferred.rb +10 -4
  116. data/lib/mongo/server_selector/secondary.rb +10 -4
  117. data/lib/mongo/server_selector/secondary_preferred.rb +24 -4
  118. data/lib/mongo/session.rb +180 -0
  119. data/lib/mongo/session/server_session.rb +73 -0
  120. data/lib/mongo/session/session_pool.rb +161 -0
  121. data/lib/mongo/uri.rb +11 -0
  122. data/lib/mongo/version.rb +1 -1
  123. data/mongo.gemspec +2 -1
  124. data/spec/mongo/auth/cr_spec.rb +12 -0
  125. data/spec/mongo/auth/ldap_spec.rb +2 -0
  126. data/spec/mongo/auth/scram/conversation_spec.rb +6 -6
  127. data/spec/mongo/auth/scram_spec.rb +25 -1
  128. data/spec/mongo/auth/user/view_spec.rb +268 -76
  129. data/spec/mongo/auth/x509_spec.rb +2 -0
  130. data/spec/mongo/bulk_write_spec.rb +435 -5
  131. data/spec/mongo/client_spec.rb +356 -39
  132. data/spec/mongo/cluster/app_metadata_spec.rb +2 -2
  133. data/spec/mongo/cluster_spec.rb +176 -0
  134. data/spec/mongo/collection/view/aggregation_spec.rb +33 -12
  135. data/spec/mongo/collection/view/builder/find_command_spec.rb +46 -6
  136. data/spec/mongo/collection/view/change_stream_spec.rb +814 -0
  137. data/spec/mongo/collection/view/map_reduce_spec.rb +94 -17
  138. data/spec/mongo/collection/view/readable_spec.rb +3 -12
  139. data/spec/mongo/collection_spec.rb +1048 -42
  140. data/spec/mongo/cursor/builder/get_more_command_spec.rb +19 -0
  141. data/spec/mongo/cursor_spec.rb +2 -2
  142. data/spec/mongo/database_spec.rb +50 -1
  143. data/spec/mongo/grid/fs_bucket_spec.rb +225 -137
  144. data/spec/mongo/grid/stream/read_spec.rb +2 -2
  145. data/spec/mongo/index/view_spec.rb +146 -8
  146. data/spec/mongo/monitoring/event/secure_spec.rb +42 -0
  147. data/spec/mongo/operation/read/query_spec.rb +2 -1
  148. data/spec/mongo/operation/specifiable_spec.rb +2 -2
  149. data/spec/mongo/operation/write/command/delete_spec.rb +96 -13
  150. data/spec/mongo/operation/write/command/insert_spec.rb +111 -12
  151. data/spec/mongo/operation/write/command/update_spec.rb +93 -10
  152. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  153. data/spec/mongo/operation/write/insert_spec.rb +1 -1
  154. data/spec/mongo/operation/write/update_spec.rb +1 -1
  155. data/spec/mongo/protocol/compressed_spec.rb +66 -0
  156. data/spec/mongo/protocol/delete_spec.rb +14 -0
  157. data/spec/mongo/protocol/get_more_spec.rb +14 -0
  158. data/spec/mongo/protocol/insert_spec.rb +14 -0
  159. data/spec/mongo/protocol/kill_cursors_spec.rb +14 -0
  160. data/spec/mongo/protocol/msg_spec.rb +499 -0
  161. data/spec/mongo/protocol/query_spec.rb +45 -0
  162. data/spec/mongo/protocol/registry_spec.rb +31 -0
  163. data/spec/mongo/protocol/reply_spec.rb +14 -0
  164. data/spec/mongo/protocol/update_spec.rb +14 -0
  165. data/spec/mongo/retryable_spec.rb +6 -2
  166. data/spec/mongo/sdam_spec.rb +4 -0
  167. data/spec/mongo/server/connection_spec.rb +4 -2
  168. data/spec/mongo/server/description_spec.rb +28 -1
  169. data/spec/mongo/session/server_session_spec.rb +16 -0
  170. data/spec/mongo/session/session_pool_spec.rb +194 -0
  171. data/spec/mongo/uri_spec.rb +31 -2
  172. data/spec/spec_helper.rb +104 -0
  173. data/spec/support/authorization.rb +6 -1
  174. data/spec/support/crud.rb +3 -1
  175. data/spec/support/crud/write.rb +6 -1
  176. data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +69 -0
  177. data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +63 -0
  178. data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +109 -0
  179. data/spec/support/sdam/rs/discover_arbiters.yml +1 -1
  180. data/spec/support/sdam/rs/discover_passives.yml +2 -2
  181. data/spec/support/sdam/rs/discover_primary.yml +1 -1
  182. data/spec/support/sdam/rs/discover_secondary.yml +1 -1
  183. data/spec/support/sdam/rs/discovery.yml +4 -4
  184. data/spec/support/sdam/rs/equal_electionids.yml +1 -0
  185. data/spec/support/sdam/rs/ghost_discovered.yml +1 -1
  186. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +1 -1
  187. data/spec/support/sdam/rs/ls_timeout.yml +88 -0
  188. data/spec/support/sdam/rs/member_reconfig.yml +2 -2
  189. data/spec/support/sdam/rs/member_standalone.yml +2 -2
  190. data/spec/support/sdam/rs/new_primary.yml +2 -2
  191. data/spec/support/sdam/rs/new_primary_new_electionid.yml +3 -0
  192. data/spec/support/sdam/rs/new_primary_new_setversion.yml +3 -0
  193. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +2 -2
  194. data/spec/support/sdam/rs/non_rs_member.yml +1 -1
  195. data/spec/support/sdam/rs/normalize_case.yml +1 -1
  196. data/spec/support/sdam/rs/null_election_id.yml +4 -0
  197. data/spec/support/sdam/rs/primary_becomes_standalone.yml +2 -2
  198. data/spec/support/sdam/rs/primary_changes_set_name.yml +2 -2
  199. data/spec/support/sdam/rs/primary_disconnect.yml +2 -2
  200. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +5 -0
  201. data/spec/support/sdam/rs/primary_disconnect_setversion.yml +5 -0
  202. data/spec/support/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +58 -0
  203. data/spec/support/sdam/rs/primary_reports_new_member.yml +4 -4
  204. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +2 -2
  205. data/spec/support/sdam/rs/primary_wrong_set_name.yml +1 -1
  206. data/spec/support/sdam/rs/response_from_removed.yml +2 -2
  207. data/spec/support/sdam/rs/rsother_discovered.yml +1 -1
  208. data/spec/support/sdam/rs/sec_not_auth.yml +1 -1
  209. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +1 -1
  210. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +2 -2
  211. data/spec/support/sdam/rs/setversion_without_electionid.yml +2 -0
  212. data/spec/support/sdam/rs/stepdown_change_set_name.yml +2 -2
  213. data/spec/support/sdam/rs/unexpected_mongos.yml +1 -1
  214. data/spec/support/sdam/rs/use_setversion_without_electionid.yml +3 -0
  215. data/spec/support/sdam/rs/wrong_set_name.yml +1 -1
  216. data/spec/support/sdam/sharded/ls_timeout_mongos.yml +97 -0
  217. data/spec/support/sdam/sharded/mongos_disconnect.yml +3 -3
  218. data/spec/support/sdam/sharded/multiple_mongoses.yml +1 -1
  219. data/spec/support/sdam/sharded/non_mongos_removed.yml +1 -1
  220. data/spec/support/sdam/sharded/normalize_uri_case.yml +1 -1
  221. data/spec/support/sdam/single/direct_connection_external_ip.yml +1 -1
  222. data/spec/support/sdam/single/direct_connection_mongos.yml +1 -1
  223. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  224. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  225. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  226. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  227. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  228. data/spec/support/sdam/single/ls_timeout_standalone.yml +35 -0
  229. data/spec/support/sdam/single/not_ok_response.yml +1 -1
  230. data/spec/support/sdam/single/standalone_removed.yml +1 -1
  231. data/spec/support/sdam/single/unavailable_seed.yml +1 -1
  232. data/spec/support/server_discovery_and_monitoring.rb +4 -0
  233. data/spec/support/shared/session.rb +236 -0
  234. metadata +53 -15
  235. metadata.gz.sig +0 -0
@@ -55,11 +55,14 @@ module Mongo
55
55
  # @example Return the event payload.
56
56
  # message.payload
57
57
  #
58
- # @return [ Hash ] The event payload.
58
+ # @return [ BSON::Document ] The event payload.
59
59
  #
60
60
  # @since 2.1.0
61
61
  def payload
62
- { reply: upconverter.command, request_id: request_id }
62
+ BSON::Document.new(
63
+ reply: upconverter.command,
64
+ request_id: request_id
65
+ )
63
66
  end
64
67
 
65
68
  private
@@ -70,9 +73,9 @@ module Mongo
70
73
 
71
74
  # The operation code required to specify a Reply message.
72
75
  # @return [Fixnum] the operation code.
73
- def op_code
74
- 1
75
- end
76
+ #
77
+ # @since 2.5.0
78
+ OP_CODE = 1
76
79
 
77
80
  # Available flags for a Reply message.
78
81
  FLAGS = [
@@ -194,6 +197,8 @@ module Mongo
194
197
  documents.first
195
198
  end
196
199
  end
200
+
201
+ Registry.register(OP_CODE, self)
197
202
  end
198
203
  end
199
204
  end
@@ -147,6 +147,169 @@ module Mongo
147
147
  end
148
148
  end
149
149
 
150
+ # MongoDB wire protocol serialization strategy for a Section of OP_MSG.
151
+ #
152
+ # Serializes and de-serializes a list of Sections.
153
+ #
154
+ # @since 2.5.0
155
+ module Sections
156
+
157
+ # Serializes the sections of an OP_MSG, payload type 0 or 1.
158
+ #
159
+ # @param [ BSON::ByteBuffer ] buffer Buffer to receive the serialized Sections.
160
+ # @param [ Array<Hash, BSON::Document> ] value The sections to be serialized.
161
+ # @param [ Fixnum ] max_bson_size The max bson size of documents in the sections.
162
+ # @param [ true, false ] validating_keys Whether to validate document keys.
163
+ #
164
+ # @return [ BSON::ByteBuffer ] Buffer with serialized value.
165
+ #
166
+ # @since 2.5.0
167
+ def self.serialize(buffer, value, max_bson_size = nil, validating_keys = BSON::Config.validating_keys?)
168
+ value.each do |section|
169
+ case section[:type]
170
+ when PayloadZero::TYPE
171
+ PayloadZero.serialize(buffer, section[:payload], max_bson_size, false)
172
+ when nil
173
+ PayloadZero.serialize(buffer, section[:payload], max_bson_size, false)
174
+ when PayloadOne::TYPE
175
+ PayloadOne.serialize(buffer, section[:payload], max_bson_size, validating_keys)
176
+ else
177
+ raise Error::UnknownPayloadType.new(section[:type])
178
+ end
179
+ end
180
+ end
181
+
182
+ # Deserializes a section of an OP_MSG from the IO stream.
183
+ #
184
+ # @param [ BSON::ByteBuffer ] buffer Buffer containing the sections.
185
+ #
186
+ # @return [ Array<BSON::Document> ] Deserialized sections.
187
+ #
188
+ # @since 2.5.0
189
+ def self.deserialize(buffer)
190
+ end_length = (@flag_bits & Msg::FLAGS.index(:checksum_present)) == 1 ? 32 : 0
191
+ sections = []
192
+ until buffer.length == end_length
193
+ case byte = buffer.get_byte
194
+ when PayloadZero::TYPE_BYTE
195
+ sections << PayloadZero.deserialize(buffer)
196
+ when PayloadOne::TYPE_BYTE
197
+ sections += PayloadOne.deserialize(buffer)
198
+ else
199
+ raise Error::UnknownPayloadType.new(byte)
200
+ end
201
+ end
202
+ sections
203
+ end
204
+
205
+ # Whether there can be a size limit on this type after serialization.
206
+ #
207
+ # @return [ true ] Documents can be size limited upon serialization.
208
+ #
209
+ # @since 2.5.0
210
+ def self.size_limited?
211
+ true
212
+ end
213
+
214
+ # MongoDB wire protocol serialization strategy for a payload 0 type Section of OP_MSG.
215
+ #
216
+ # @since 2.5.0
217
+ module PayloadZero
218
+
219
+ # The byte identifier for this payload type.
220
+ #
221
+ # @since 2.5.0
222
+ TYPE = 0x0
223
+
224
+ # The byte corresponding to this payload type.
225
+ #
226
+ # @since 2.5.0
227
+ TYPE_BYTE = TYPE.chr.force_encoding(BSON::BINARY).freeze
228
+
229
+ # Serializes a section of an OP_MSG, payload type 0.
230
+ #
231
+ # @param [ BSON::ByteBuffer ] buffer Buffer to receive the serialized Sections.
232
+ # @param [ BSON::Document, Hash ] value The object to serialize.
233
+ # @param [ Fixnum ] max_bson_size The max bson size of documents in the section.
234
+ # @param [ true, false ] validating_keys Whether to validate document keys.
235
+ #
236
+ # @return [ BSON::ByteBuffer ] Buffer with serialized value.
237
+ #
238
+ # @since 2.5.0
239
+ def self.serialize(buffer, value, max_bson_size = nil, validating_keys = BSON::Config.validating_keys?)
240
+ buffer.put_byte(TYPE_BYTE)
241
+ Serializers::Document.serialize(buffer, value, max_bson_size, validating_keys)
242
+ end
243
+
244
+ # Deserializes a section of payload type 0 of an OP_MSG from the IO stream.
245
+ #
246
+ # @param [ BSON::ByteBuffer ] buffer Buffer containing the sections.
247
+ #
248
+ # @return [ Array<BSON::Document> ] Deserialized section.
249
+ #
250
+ # @since 2.5.0
251
+ def self.deserialize(buffer)
252
+ BSON::Document.from_bson(buffer)
253
+ end
254
+ end
255
+
256
+ # MongoDB wire protocol serialization strategy for a payload 1 type Section of OP_MSG.
257
+ #
258
+ # @since 2.5.0
259
+ module PayloadOne
260
+
261
+ # The byte identifier for this payload type.
262
+ #
263
+ # @since 2.5.0
264
+ TYPE = 0x1
265
+
266
+ # The byte corresponding to this payload type.
267
+ #
268
+ # @since 2.5.0
269
+ TYPE_BYTE = TYPE.chr.force_encoding(BSON::BINARY).freeze
270
+
271
+ # Serializes a section of an OP_MSG, payload type 1.
272
+ #
273
+ # @param [ BSON::ByteBuffer ] buffer Buffer to receive the serialized Sections.
274
+ # @param [ BSON::Document, Hash ] value The object to serialize.
275
+ # @param [ Fixnum ] max_bson_size The max bson size of documents in the section.
276
+ # @param [ true, false ] validating_keys Whether to validate document keys.
277
+ #
278
+ # @return [ BSON::ByteBuffer ] Buffer with serialized value.
279
+ #
280
+ # @since 2.5.0
281
+ def self.serialize(buffer, value, max_bson_size = nil, validating_keys = BSON::Config.validating_keys?)
282
+ buffer.put_byte(TYPE_BYTE)
283
+ start = buffer.length
284
+ buffer.put_int32(0) # hold for size
285
+ buffer.put_cstring(value[:identifier])
286
+ value[:sequence].each do |document|
287
+ Document.serialize(buffer, document, max_bson_size, validating_keys)
288
+ end
289
+ buffer.replace_int32(start, buffer.length - start)
290
+ end
291
+
292
+ # Deserializes a section of payload type 1 of an OP_MSG from the IO stream.
293
+ #
294
+ # @param [ BSON::ByteBuffer ] buffer Buffer containing the sections.
295
+ #
296
+ # @return [ Array<BSON::Document> ] Deserialized section.
297
+ #
298
+ # @since 2.5.0
299
+ def self.deserialize(buffer)
300
+ start_size = buffer.length
301
+ section_size = buffer.get_int32 # get the size
302
+ end_size = start_size - section_size
303
+ buffer.get_cstring # get the identifier
304
+ documents = []
305
+ until buffer.length == end_size
306
+ documents << BSON::Document.from_bson(buffer)
307
+ end
308
+ documents
309
+ end
310
+ end
311
+ end
312
+
150
313
  # MongoDB wire protocol serialization strategy for a BSON Document.
151
314
  #
152
315
  # Serializes and de-serializes a single document.
@@ -184,6 +347,67 @@ module Mongo
184
347
  true
185
348
  end
186
349
  end
350
+
351
+ # MongoDB wire protocol serialization strategy for a single byte.
352
+ #
353
+ # Writes and fetches a single byte from the byte buffer.
354
+ module Byte
355
+
356
+ # Writes a byte into the buffer.
357
+ #
358
+ # @param buffer [ BSON::ByteBuffer ] buffer Buffer to receive the single byte.
359
+ # @param value [ String ] value The byte to write to the buffer.
360
+ # @param value [ true, false ] validating_keys Whether to validate keys.
361
+ #
362
+ # @return [ BSON::ByteBuffer ] Buffer with serialized value.
363
+ #
364
+ # @since 2.5.0
365
+ def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
366
+ buffer.put_byte(value)
367
+ end
368
+
369
+ # Deserializes a byte from the byte buffer.
370
+ #
371
+ # @param [ BSON::ByteBuffer ] buffer Buffer containing the value to read.
372
+ #
373
+ # @return [ String ] The byte.
374
+ #
375
+ # @since 2.5.0
376
+ def self.deserialize(buffer)
377
+ buffer.get_byte
378
+ end
379
+ end
380
+
381
+ # MongoDB wire protocol serialization strategy for n bytes.
382
+ #
383
+ # Writes and fetches bytes from the byte buffer.
384
+ module Bytes
385
+
386
+ # Writes bytes into the buffer.
387
+ #
388
+ # @param buffer [ BSON::ByteBuffer ] buffer Buffer to receive the bytes.
389
+ # @param value [ String ] value The bytes to write to the buffer.
390
+ # @param value [ true, false ] validating_keys Whether to validate keys.
391
+ #
392
+ # @return [ BSON::ByteBuffer ] Buffer with serialized value.
393
+ #
394
+ # @since 2.5.0
395
+ def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
396
+ buffer.put_bytes(value)
397
+ end
398
+
399
+ # Deserializes bytes from the byte buffer.
400
+ #
401
+ # @param [ BSON::ByteBuffer ] buffer Buffer containing the value to read.
402
+ # @param [ Integer ] num_bytes Number of bytes to read.
403
+ #
404
+ # @return [ String ] The bytes.
405
+ #
406
+ # @since 2.5.0
407
+ def self.deserialize(buffer, num_bytes = nil)
408
+ buffer.get_bytes(num_bytes || buffer.length)
409
+ end
410
+ end
187
411
  end
188
412
  end
189
413
  end
@@ -67,16 +67,16 @@ module Mongo
67
67
  # @example Return the event payload.
68
68
  # message.payload
69
69
  #
70
- # @return [ Hash ] The event payload.
70
+ # @return [ BSON::Document ] The event payload.
71
71
  #
72
72
  # @since 2.1.0
73
73
  def payload
74
- {
74
+ BSON::Document.new(
75
75
  command_name: 'update',
76
76
  database_name: @database,
77
77
  command: upconverter.command,
78
78
  request_id: request_id
79
- }
79
+ )
80
80
  end
81
81
 
82
82
  protected
@@ -87,9 +87,9 @@ module Mongo
87
87
 
88
88
  # The operation code required to specify an Update message.
89
89
  # @return [Fixnum] the operation code.
90
- def op_code
91
- 2001
92
- end
90
+ #
91
+ # @since 2.5.0
92
+ OP_CODE = 2001
93
93
 
94
94
  # Available flags for an Update message.
95
95
  FLAGS = [:upsert, :multi_update]
@@ -200,6 +200,8 @@ module Mongo
200
200
  document
201
201
  end
202
202
  end
203
+
204
+ Registry.register(OP_CODE, self)
203
205
  end
204
206
  end
205
207
  end
@@ -33,6 +33,8 @@ module Mongo
33
33
  # @param [ Integer ] attempt The retry attempt count - for internal use.
34
34
  # @param [ Proc ] block The block to execute.
35
35
  #
36
+ # @yieldparam [ Server ] server The server to which the write should be sent.
37
+ #
36
38
  # @return [ Result ] The result of the operation.
37
39
  #
38
40
  # @since 2.1.0
@@ -97,11 +99,11 @@ module Mongo
97
99
  # @return [ Result ] The result of the operation.
98
100
  #
99
101
  # @since 2.1.0
100
- def write_with_retry
102
+ def write_with_retry(session, server_selector)
101
103
  attempt = 0
102
104
  begin
103
105
  attempt += 1
104
- yield
106
+ yield(server_selector.call)
105
107
  rescue Error::OperationFailure => e
106
108
  raise(e) if attempt > Cluster::MAX_WRITE_RETRIES
107
109
  if e.write_retryable?
data/lib/mongo/server.rb CHANGED
@@ -50,7 +50,7 @@ module Mongo
50
50
  CONNECT_TIMEOUT = 10.freeze
51
51
 
52
52
  # Get the description from the monitor and scan on monitor.
53
- def_delegators :monitor, :description, :scan!, :heartbeat_frequency, :last_scan
53
+ def_delegators :monitor, :description, :scan!, :heartbeat_frequency, :last_scan, :compressor
54
54
  alias :heartbeat_frequency_seconds :heartbeat_frequency
55
55
 
56
56
  # Delegate convenience methods to the monitor description.
@@ -72,11 +72,14 @@ module Mongo
72
72
  :standalone?,
73
73
  :unknown?,
74
74
  :unknown!,
75
- :last_write_date
75
+ :last_write_date,
76
+ :logical_session_timeout
76
77
 
77
78
  # Get the app metadata from the cluster.
78
79
  def_delegators :cluster,
79
- :app_metadata
80
+ :app_metadata,
81
+ :cluster_time,
82
+ :update_cluster_time
80
83
 
81
84
  # Is this server equal to another?
82
85
  #
@@ -99,7 +99,7 @@ module Mongo
99
99
 
100
100
  def read(request_id = nil)
101
101
  ensure_connected do |socket|
102
- Protocol::Reply.deserialize(socket, max_message_size, request_id)
102
+ Protocol::Message.deserialize(socket, max_message_size, request_id)
103
103
  end
104
104
  end
105
105
  end
@@ -29,22 +29,40 @@ module Mongo
29
29
  # @since 2.1.0
30
30
  PING = { :ping => 1 }.freeze
31
31
 
32
+ # The ping command for an OP_MSG (server versions >= 3.6).
33
+ #
34
+ # @since 2.5.0
35
+ PING_OP_MSG = { :ping => 1, '$db' => Database::ADMIN }.freeze
36
+
32
37
  # Ping message.
33
38
  #
34
39
  # @since 2.1.0
35
40
  PING_MESSAGE = Protocol::Query.new(Database::ADMIN, Database::COMMAND, PING, :limit => -1)
36
41
 
42
+ # Ping message as an OP_MSG (server versions >= 3.6).
43
+ #
44
+ # @since 2.5.0
45
+ PING_OP_MSG_MESSAGE = Protocol::Msg.new([:none], {}, PING_OP_MSG)
46
+
37
47
  # The ping message as raw bytes.
38
48
  #
39
49
  # @since 2.1.0
40
50
  PING_BYTES = PING_MESSAGE.serialize.to_s.freeze
41
51
 
52
+ # The ping OP_MSG message as raw bytes (server versions >= 3.6).
53
+ #
54
+ # @since 2.5.0
55
+ PING_OP_MSG_BYTES = PING_OP_MSG_MESSAGE.serialize.to_s.freeze
56
+
42
57
  def_delegators :@server,
43
58
  :features,
44
59
  :max_bson_object_size,
45
60
  :max_message_size,
46
61
  :mongos?,
47
- :app_metadata
62
+ :app_metadata,
63
+ :compressor,
64
+ :cluster_time,
65
+ :update_cluster_time
48
66
 
49
67
  # Tell the underlying socket to establish a connection to the host.
50
68
  #
@@ -99,7 +117,7 @@ module Mongo
99
117
  # @param [ Array<Message> ] messages The messages to dispatch.
100
118
  # @param [ Integer ] operation_id The operation id to link messages.
101
119
  #
102
- # @return [ Protocol::Reply ] The reply if needed.
120
+ # @return [ Protocol::Message ] The reply if needed.
103
121
  #
104
122
  # @since 2.0.0
105
123
  def dispatch(messages, operation_id = nil)
@@ -149,9 +167,10 @@ module Mongo
149
167
  #
150
168
  # @since 2.1.0
151
169
  def ping
170
+ bytes = features.op_msg_enabled? ? PING_OP_MSG_BYTES : PING_BYTES
152
171
  ensure_connected do |socket|
153
- socket.write(PING_BYTES)
154
- reply = Protocol::Reply.deserialize(socket, max_message_size)
172
+ socket.write(bytes)
173
+ reply = Protocol::Message.deserialize(socket, max_message_size)
155
174
  reply.documents[0][Operation::Result::OK] == 1
156
175
  end
157
176
  end
@@ -180,7 +199,7 @@ module Mongo
180
199
  def handshake!
181
200
  if socket && socket.connectable?
182
201
  socket.write(app_metadata.ismaster_bytes)
183
- response = Protocol::Reply.deserialize(socket, max_message_size).documents[0]
202
+ response = Protocol::Message.deserialize(socket, max_message_size).documents[0]
184
203
  min_wire_version = response[Description::MIN_WIRE_VERSION] || Description::LEGACY_WIRE_VERSION
185
204
  max_wire_version = response[Description::MAX_WIRE_VERSION] || Description::LEGACY_WIRE_VERSION
186
205
  features = Description::Features.new(min_wire_version..max_wire_version)
@@ -190,9 +209,12 @@ module Mongo
190
209
 
191
210
  def authenticate!
192
211
  if options[:user] || options[:auth_mech]
193
- user = Auth::User.new(Options::Redacted.new(:auth_mech => default_mechanism).merge(options))
212
+ user = Auth::User.new(Options::Redacted.new(:auth_mech => default_mechanism, :client_key => @client_key).merge(options))
213
+
194
214
  @server.handle_auth_failure! do
195
- Auth.get(user).login(self)
215
+ reply = Auth.get(user).login(self)
216
+ @client_key ||= user.send(:client_key) if user.mechanism == :scram
217
+ reply
196
218
  end
197
219
  end
198
220
  end
@@ -204,7 +226,7 @@ module Mongo
204
226
  def write(messages, buffer = BSON::ByteBuffer.new)
205
227
  start_size = 0
206
228
  messages.each do |message|
207
- message.serialize(buffer, max_bson_object_size)
229
+ message.compress!(compressor, options[:zlib_compression_level]).serialize(buffer, max_bson_object_size)
208
230
  if max_message_size &&
209
231
  (buffer.length - start_size) > max_message_size
210
232
  raise Error::MaxMessageSize.new(max_message_size)