mongo 2.4.3 → 2.5.0.beta

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.
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)