mongo 2.5.3 → 2.6.0

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 (394) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE +1 -1
  5. data/README.md +3 -2
  6. data/lib/mongo.rb +2 -2
  7. data/lib/mongo/address.rb +10 -2
  8. data/lib/mongo/address/ipv4.rb +1 -1
  9. data/lib/mongo/address/ipv6.rb +26 -5
  10. data/lib/mongo/address/unix.rb +1 -1
  11. data/lib/mongo/auth.rb +10 -3
  12. data/lib/mongo/auth/cr.rb +4 -1
  13. data/lib/mongo/auth/cr/conversation.rb +4 -1
  14. data/lib/mongo/auth/ldap.rb +1 -1
  15. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  16. data/lib/mongo/auth/roles.rb +1 -1
  17. data/lib/mongo/auth/scram.rb +24 -7
  18. data/lib/mongo/auth/scram/conversation.rb +52 -19
  19. data/lib/mongo/auth/stringprep.rb +114 -0
  20. data/lib/mongo/auth/stringprep/profiles/sasl.rb +73 -0
  21. data/lib/mongo/auth/stringprep/tables.rb +3232 -0
  22. data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +174 -0
  23. data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +1170 -0
  24. data/lib/mongo/auth/user.rb +14 -3
  25. data/lib/mongo/auth/user/view.rb +1 -1
  26. data/lib/mongo/auth/x509.rb +1 -1
  27. data/lib/mongo/auth/x509/conversation.rb +1 -1
  28. data/lib/mongo/bson.rb +1 -1
  29. data/lib/mongo/bulk_write.rb +8 -8
  30. data/lib/mongo/bulk_write/combineable.rb +1 -1
  31. data/lib/mongo/bulk_write/ordered_combiner.rb +1 -1
  32. data/lib/mongo/bulk_write/result.rb +1 -1
  33. data/lib/mongo/bulk_write/result_combiner.rb +4 -4
  34. data/lib/mongo/bulk_write/transformable.rb +1 -1
  35. data/lib/mongo/bulk_write/unordered_combiner.rb +1 -1
  36. data/lib/mongo/bulk_write/validatable.rb +1 -1
  37. data/lib/mongo/client.rb +115 -24
  38. data/lib/mongo/cluster.rb +17 -10
  39. data/lib/mongo/cluster/app_metadata.rb +7 -1
  40. data/lib/mongo/cluster/periodic_executor.rb +1 -1
  41. data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -1
  42. data/lib/mongo/cluster/topology.rb +12 -2
  43. data/lib/mongo/cluster/topology/replica_set.rb +9 -1
  44. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  45. data/lib/mongo/cluster/topology/single.rb +1 -1
  46. data/lib/mongo/cluster/topology/unknown.rb +1 -1
  47. data/lib/mongo/collection.rb +75 -19
  48. data/lib/mongo/collection/view.rb +1 -1
  49. data/lib/mongo/collection/view/aggregation.rb +1 -1
  50. data/lib/mongo/collection/view/builder.rb +1 -1
  51. data/lib/mongo/collection/view/builder/aggregation.rb +3 -3
  52. data/lib/mongo/collection/view/builder/find_command.rb +1 -1
  53. data/lib/mongo/collection/view/builder/flags.rb +1 -1
  54. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  55. data/lib/mongo/collection/view/builder/modifiers.rb +1 -1
  56. data/lib/mongo/collection/view/builder/op_query.rb +1 -1
  57. data/lib/mongo/collection/view/change_stream.rb +193 -17
  58. data/lib/mongo/collection/view/change_stream/retryable.rb +3 -20
  59. data/lib/mongo/collection/view/explainable.rb +1 -1
  60. data/lib/mongo/collection/view/immutable.rb +1 -1
  61. data/lib/mongo/collection/view/iterable.rb +2 -2
  62. data/lib/mongo/collection/view/map_reduce.rb +1 -1
  63. data/lib/mongo/collection/view/readable.rb +108 -29
  64. data/lib/mongo/collection/view/writable.rb +3 -3
  65. data/lib/mongo/cursor.rb +44 -4
  66. data/lib/mongo/cursor/builder.rb +1 -1
  67. data/lib/mongo/cursor/builder/get_more_command.rb +1 -1
  68. data/lib/mongo/cursor/builder/kill_cursors_command.rb +1 -1
  69. data/lib/mongo/cursor/builder/op_get_more.rb +1 -1
  70. data/lib/mongo/cursor/builder/op_kill_cursors.rb +1 -1
  71. data/lib/mongo/database.rb +46 -3
  72. data/lib/mongo/database/view.rb +11 -11
  73. data/lib/mongo/dbref.rb +1 -1
  74. data/lib/mongo/error.rb +57 -1
  75. data/lib/mongo/error/bulk_write_error.rb +2 -2
  76. data/lib/mongo/error/change_stream_resumable.rb +37 -0
  77. data/lib/mongo/error/closed_stream.rb +1 -1
  78. data/lib/mongo/error/extra_file_chunk.rb +1 -1
  79. data/lib/mongo/error/failed_stringprep_validation.rb +38 -0
  80. data/lib/mongo/error/file_not_found.rb +1 -1
  81. data/lib/mongo/error/insufficient_iteration_count.rb +38 -0
  82. data/lib/mongo/error/invalid_application_name.rb +1 -1
  83. data/lib/mongo/error/invalid_bulk_operation.rb +1 -1
  84. data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -1
  85. data/lib/mongo/error/invalid_collection_name.rb +1 -1
  86. data/lib/mongo/error/invalid_database_name.rb +1 -1
  87. data/lib/mongo/error/invalid_document.rb +1 -1
  88. data/lib/mongo/error/invalid_file.rb +1 -1
  89. data/lib/mongo/error/invalid_file_revision.rb +1 -1
  90. data/lib/mongo/error/invalid_min_pool_size.rb +1 -1
  91. data/lib/mongo/error/invalid_nonce.rb +1 -1
  92. data/lib/mongo/error/invalid_read_option.rb +35 -0
  93. data/lib/mongo/error/invalid_replacement_document.rb +1 -1
  94. data/lib/mongo/error/invalid_server_preference.rb +1 -1
  95. data/lib/mongo/error/invalid_session.rb +1 -1
  96. data/lib/mongo/error/invalid_signature.rb +1 -1
  97. data/lib/mongo/error/invalid_transaction_operation.rb +82 -0
  98. data/lib/mongo/error/invalid_txt_record.rb +1 -1
  99. data/lib/mongo/error/invalid_update_document.rb +1 -1
  100. data/lib/mongo/error/invalid_uri.rb +1 -1
  101. data/lib/mongo/error/invalid_write_concern.rb +1 -1
  102. data/lib/mongo/error/max_bson_size.rb +1 -1
  103. data/lib/mongo/error/max_message_size.rb +1 -1
  104. data/lib/mongo/error/mismatched_domain.rb +1 -1
  105. data/lib/mongo/error/missing_file_chunk.rb +1 -1
  106. data/lib/mongo/error/missing_resume_token.rb +1 -1
  107. data/lib/mongo/error/multi_index_drop.rb +1 -1
  108. data/lib/mongo/error/need_primary_server.rb +1 -1
  109. data/lib/mongo/error/no_server_available.rb +1 -1
  110. data/lib/mongo/error/no_srv_records.rb +1 -1
  111. data/lib/mongo/error/operation_failure.rb +108 -14
  112. data/lib/mongo/error/parser.rb +50 -1
  113. data/lib/mongo/error/socket_error.rb +5 -2
  114. data/lib/mongo/error/socket_timeout_error.rb +5 -2
  115. data/lib/mongo/error/unchangeable_collection_option.rb +1 -1
  116. data/lib/mongo/error/unexpected_chunk_length.rb +1 -1
  117. data/lib/mongo/error/unexpected_response.rb +1 -1
  118. data/lib/mongo/error/unknown_payload_type.rb +1 -1
  119. data/lib/mongo/error/unsupported_array_filters.rb +1 -1
  120. data/lib/mongo/error/unsupported_collation.rb +1 -1
  121. data/lib/mongo/error/unsupported_features.rb +1 -1
  122. data/lib/mongo/error/unsupported_message_type.rb +1 -1
  123. data/lib/mongo/error/write_retryable.rb +27 -0
  124. data/lib/mongo/event.rb +10 -9
  125. data/lib/mongo/event/base.rb +33 -0
  126. data/lib/mongo/event/description_changed.rb +2 -2
  127. data/lib/mongo/event/listeners.rb +1 -1
  128. data/lib/mongo/event/member_discovered.rb +4 -2
  129. data/lib/mongo/event/primary_elected.rb +2 -2
  130. data/lib/mongo/event/publisher.rb +1 -1
  131. data/lib/mongo/event/standalone_discovered.rb +2 -2
  132. data/lib/mongo/event/subscriber.rb +1 -1
  133. data/lib/mongo/grid.rb +1 -1
  134. data/lib/mongo/grid/file.rb +1 -1
  135. data/lib/mongo/grid/file/chunk.rb +3 -3
  136. data/lib/mongo/grid/file/info.rb +26 -3
  137. data/lib/mongo/grid/fs_bucket.rb +1 -1
  138. data/lib/mongo/grid/stream.rb +1 -1
  139. data/lib/mongo/grid/stream/read.rb +1 -1
  140. data/lib/mongo/grid/stream/write.rb +1 -1
  141. data/lib/mongo/index.rb +1 -1
  142. data/lib/mongo/index/view.rb +1 -1
  143. data/lib/mongo/loggable.rb +1 -1
  144. data/lib/mongo/logger.rb +1 -1
  145. data/lib/mongo/monitoring.rb +99 -62
  146. data/lib/mongo/monitoring/command_log_subscriber.rb +2 -2
  147. data/lib/mongo/monitoring/event.rb +2 -1
  148. data/lib/mongo/monitoring/event/command_failed.rb +19 -6
  149. data/lib/mongo/monitoring/event/command_started.rb +14 -3
  150. data/lib/mongo/monitoring/event/command_succeeded.rb +5 -3
  151. data/lib/mongo/monitoring/event/secure.rb +1 -1
  152. data/lib/mongo/monitoring/event/server_closed.rb +2 -2
  153. data/lib/mongo/monitoring/event/server_description_changed.rb +2 -2
  154. data/lib/mongo/monitoring/event/server_opening.rb +11 -2
  155. data/lib/mongo/monitoring/event/topology_changed.rb +13 -2
  156. data/lib/mongo/monitoring/event/topology_closed.rb +2 -2
  157. data/lib/mongo/monitoring/event/topology_opening.rb +11 -2
  158. data/lib/mongo/monitoring/publishable.rb +10 -6
  159. data/lib/mongo/monitoring/sdam_log_subscriber.rb +1 -1
  160. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +1 -1
  161. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +1 -1
  162. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +1 -1
  163. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  164. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +1 -1
  165. data/lib/mongo/operation/aggregate/op_msg.rb +3 -0
  166. data/lib/mongo/operation/create/op_msg.rb +9 -0
  167. data/lib/mongo/operation/create_index/op_msg.rb +9 -0
  168. data/lib/mongo/operation/create_user/command.rb +1 -1
  169. data/lib/mongo/operation/create_user/op_msg.rb +10 -1
  170. data/lib/mongo/operation/delete/op_msg.rb +3 -0
  171. data/lib/mongo/operation/distinct/op_msg.rb +9 -0
  172. data/lib/mongo/operation/drop/op_msg.rb +9 -0
  173. data/lib/mongo/operation/drop_database/op_msg.rb +9 -0
  174. data/lib/mongo/operation/drop_index/op_msg.rb +9 -0
  175. data/lib/mongo/operation/explain/op_msg.rb +3 -0
  176. data/lib/mongo/operation/find/op_msg.rb +3 -0
  177. data/lib/mongo/operation/get_more.rb +1 -1
  178. data/lib/mongo/operation/get_more/command.rb +1 -1
  179. data/lib/mongo/operation/get_more/legacy.rb +1 -1
  180. data/lib/mongo/operation/get_more/op_msg.rb +3 -0
  181. data/lib/mongo/operation/indexes/op_msg.rb +3 -0
  182. data/lib/mongo/operation/indexes/result.rb +1 -1
  183. data/lib/mongo/operation/insert/bulk_result.rb +32 -2
  184. data/lib/mongo/operation/insert/op_msg.rb +3 -0
  185. data/lib/mongo/operation/insert/result.rb +1 -1
  186. data/lib/mongo/operation/kill_cursors/op_msg.rb +9 -0
  187. data/lib/mongo/operation/list_collections/op_msg.rb +3 -0
  188. data/lib/mongo/operation/list_collections/result.rb +5 -1
  189. data/lib/mongo/operation/map_reduce/op_msg.rb +3 -0
  190. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  191. data/lib/mongo/operation/parallel_scan/op_msg.rb +3 -0
  192. data/lib/mongo/operation/remove_user/op_msg.rb +9 -0
  193. data/lib/mongo/operation/result.rb +27 -14
  194. data/lib/mongo/operation/shared/executable.rb +1 -0
  195. data/lib/mongo/operation/shared/sessions_supported.rb +78 -7
  196. data/lib/mongo/operation/shared/specifiable.rb +18 -2
  197. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -1
  198. data/lib/mongo/operation/update/op_msg.rb +3 -0
  199. data/lib/mongo/operation/update_user/command.rb +1 -1
  200. data/lib/mongo/operation/update_user/op_msg.rb +10 -1
  201. data/lib/mongo/operation/users_info/op_msg.rb +3 -0
  202. data/lib/mongo/options.rb +1 -1
  203. data/lib/mongo/options/mapper.rb +1 -1
  204. data/lib/mongo/options/redacted.rb +1 -1
  205. data/lib/mongo/protocol/bit_vector.rb +1 -1
  206. data/lib/mongo/protocol/compressed.rb +1 -1
  207. data/lib/mongo/protocol/delete.rb +1 -1
  208. data/lib/mongo/protocol/get_more.rb +7 -7
  209. data/lib/mongo/protocol/insert.rb +1 -1
  210. data/lib/mongo/protocol/kill_cursors.rb +1 -1
  211. data/lib/mongo/protocol/message.rb +5 -5
  212. data/lib/mongo/protocol/msg.rb +9 -7
  213. data/lib/mongo/protocol/query.rb +1 -1
  214. data/lib/mongo/protocol/registry.rb +1 -1
  215. data/lib/mongo/protocol/reply.rb +10 -10
  216. data/lib/mongo/protocol/serializers.rb +1 -1
  217. data/lib/mongo/protocol/update.rb +1 -1
  218. data/lib/mongo/retryable.rb +22 -14
  219. data/lib/mongo/server.rb +1 -1
  220. data/lib/mongo/server/connectable.rb +1 -1
  221. data/lib/mongo/server/connection.rb +16 -4
  222. data/lib/mongo/server/connection_pool.rb +1 -1
  223. data/lib/mongo/server/connection_pool/queue.rb +1 -1
  224. data/lib/mongo/server/context.rb +1 -1
  225. data/lib/mongo/server/description.rb +14 -2
  226. data/lib/mongo/server/description/features.rb +10 -9
  227. data/lib/mongo/server/description/inspector.rb +1 -1
  228. data/lib/mongo/server/description/inspector/description_changed.rb +1 -1
  229. data/lib/mongo/server/description/inspector/member_discovered.rb +1 -1
  230. data/lib/mongo/server/description/inspector/primary_elected.rb +1 -1
  231. data/lib/mongo/server/description/inspector/standalone_discovered.rb +1 -1
  232. data/lib/mongo/server/monitor.rb +15 -3
  233. data/lib/mongo/server/monitor/connection.rb +1 -1
  234. data/lib/mongo/server_selector.rb +1 -1
  235. data/lib/mongo/server_selector/nearest.rb +1 -1
  236. data/lib/mongo/server_selector/primary.rb +1 -1
  237. data/lib/mongo/server_selector/primary_preferred.rb +1 -1
  238. data/lib/mongo/server_selector/secondary.rb +1 -1
  239. data/lib/mongo/server_selector/secondary_preferred.rb +1 -1
  240. data/lib/mongo/server_selector/selectable.rb +7 -2
  241. data/lib/mongo/session.rb +389 -12
  242. data/lib/mongo/session/server_session.rb +7 -2
  243. data/lib/mongo/session/session_pool.rb +1 -1
  244. data/lib/mongo/socket.rb +1 -1
  245. data/lib/mongo/socket/ssl.rb +1 -1
  246. data/lib/mongo/socket/tcp.rb +1 -1
  247. data/lib/mongo/socket/unix.rb +1 -1
  248. data/lib/mongo/uri.rb +6 -4
  249. data/lib/mongo/uri/srv_protocol.rb +1 -1
  250. data/lib/mongo/version.rb +2 -2
  251. data/lib/mongo/write_concern.rb +1 -1
  252. data/lib/mongo/write_concern/acknowledged.rb +1 -1
  253. data/lib/mongo/write_concern/normalizable.rb +1 -1
  254. data/lib/mongo/write_concern/unacknowledged.rb +1 -1
  255. data/mongo.gemspec +4 -1
  256. data/spec/atlas/atlas_connectivity_spec.rb +54 -0
  257. data/spec/integration/bulk_insert_spec.rb +78 -0
  258. data/spec/integration/change_stream_spec.rb +365 -0
  259. data/spec/integration/command_monitoring_spec.rb +92 -0
  260. data/spec/lite_spec_helper.rb +63 -0
  261. data/spec/mongo/address/ipv6_spec.rb +29 -1
  262. data/spec/mongo/address_spec.rb +34 -0
  263. data/spec/mongo/auth/scram/conversation_spec.rb +326 -120
  264. data/spec/mongo/auth/scram/negotiation_spec.rb +574 -0
  265. data/spec/mongo/auth/scram_spec.rb +107 -38
  266. data/spec/mongo/auth/stringprep/profiles/sasl_spec.rb +113 -0
  267. data/spec/mongo/auth/stringprep_spec.rb +188 -0
  268. data/spec/mongo/auth/user/view_spec.rb +5 -2
  269. data/spec/mongo/auth/user_spec.rb +1 -1
  270. data/spec/mongo/bulk_write/result_spec.rb +120 -0
  271. data/spec/mongo/bulk_write_spec.rb +42 -2
  272. data/spec/mongo/client_spec.rb +121 -9
  273. data/spec/mongo/cluster/app_metadata_spec.rb +14 -1
  274. data/spec/mongo/cluster/topology_spec.rb +1 -23
  275. data/spec/mongo/collection/view/change_stream_spec.rb +62 -180
  276. data/spec/mongo/collection_spec.rb +45 -12
  277. data/spec/mongo/cursor/builder/get_more_command_spec.rb +7 -7
  278. data/spec/mongo/cursor_spec.rb +2 -2
  279. data/spec/mongo/database_spec.rb +3 -3
  280. data/spec/mongo/docs_examples_spec.rb +194 -0
  281. data/spec/mongo/error/operation_failure_spec.rb +152 -0
  282. data/spec/mongo/error/parser_spec.rb +127 -0
  283. data/spec/mongo/grid/fs_bucket_spec.rb +32 -0
  284. data/spec/mongo/grid/stream/write_spec.rb +40 -1
  285. data/spec/mongo/monitoring/event/command_failed_spec.rb +30 -0
  286. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -4
  287. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +29 -7
  288. data/spec/mongo/monitoring_spec.rb +28 -3
  289. data/spec/mongo/protocol/get_more_spec.rb +2 -2
  290. data/spec/mongo/retryable_spec.rb +252 -34
  291. data/spec/mongo/retryable_writes_spec.rb +468 -544
  292. data/spec/mongo/server/connection_spec.rb +5 -5
  293. data/spec/mongo/server/description_spec.rb +23 -6
  294. data/spec/mongo/session/server_session_spec.rb +2 -2
  295. data/spec/mongo/session/session_pool_spec.rb +2 -2
  296. data/spec/mongo/transactions_examples_spec.rb +227 -0
  297. data/spec/mongo/transactions_spec.rb +44 -0
  298. data/spec/spec_helper.rb +135 -49
  299. data/spec/spec_tests/change_streams_spec.rb +42 -0
  300. data/spec/{mongo → spec_tests}/command_monitoring_spec.rb +8 -2
  301. data/spec/{mongo → spec_tests}/connection_string_spec.rb +1 -1
  302. data/spec/{mongo → spec_tests}/crud_spec.rb +5 -7
  303. data/spec/{mongo → spec_tests}/dns_seedlist_discovery_spec.rb +1 -1
  304. data/spec/{mongo → spec_tests}/gridfs_spec.rb +0 -0
  305. data/spec/{mongo → spec_tests}/max_staleness_spec.rb +0 -0
  306. data/spec/spec_tests/retryable_writes_spec.rb +78 -0
  307. data/spec/{mongo → spec_tests}/sdam_monitoring_spec.rb +4 -3
  308. data/spec/{mongo → spec_tests}/sdam_spec.rb +7 -7
  309. data/spec/{mongo → spec_tests}/server_selection_rtt_spec.rb +0 -0
  310. data/spec/{mongo → spec_tests}/server_selection_spec.rb +0 -0
  311. data/spec/support/authorization.rb +18 -6
  312. data/spec/support/change_streams.rb +265 -0
  313. data/spec/support/change_streams/operation.rb +62 -0
  314. data/spec/support/change_streams_tests/change-streams-errors.yml +53 -0
  315. data/spec/support/change_streams_tests/change-streams.yml +299 -0
  316. data/spec/support/command_monitoring.rb +1 -1
  317. data/spec/support/command_monitoring/bulkWrite.yml +4 -28
  318. data/spec/support/command_monitoring/command.yml +19 -0
  319. data/spec/support/command_monitoring/find.yml +17 -19
  320. data/spec/support/command_monitoring/insertMany.yml +2 -8
  321. data/spec/support/command_monitoring/unacknowledgedBulkWrite.yml +34 -0
  322. data/spec/support/connection_string.rb +1 -1
  323. data/spec/support/constraints.rb +56 -0
  324. data/spec/support/crud.rb +9 -4
  325. data/spec/support/crud/read.rb +24 -3
  326. data/spec/support/crud/write.rb +7 -2
  327. data/spec/support/crud_tests/read/count-collation.yml +12 -2
  328. data/spec/support/crud_tests/read/count.yml +43 -5
  329. data/spec/support/gridfs.rb +1 -1
  330. data/spec/support/primary_socket.rb +21 -0
  331. data/spec/support/retryable_writes_tests/bulkWrite-serverErrors.yml +90 -0
  332. data/spec/support/retryable_writes_tests/bulkWrite.yml +99 -1
  333. data/spec/support/retryable_writes_tests/deleteOne-serverErrors.yml +50 -0
  334. data/spec/support/retryable_writes_tests/deleteOne.yml +10 -1
  335. data/spec/support/retryable_writes_tests/findOneAndDelete-serverErrors.yml +50 -0
  336. data/spec/support/retryable_writes_tests/findOneAndDelete.yml +39 -30
  337. data/spec/support/retryable_writes_tests/findOneAndReplace-serverErrors.yml +54 -0
  338. data/spec/support/retryable_writes_tests/findOneAndReplace.yml +9 -0
  339. data/spec/support/retryable_writes_tests/findOneAndUpdate-serverErrors.yml +54 -0
  340. data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +9 -0
  341. data/spec/support/retryable_writes_tests/insertMany-serverErrors.yml +59 -0
  342. data/spec/support/retryable_writes_tests/insertMany.yml +11 -6
  343. data/spec/support/retryable_writes_tests/insertOne-serverErrors.yml +471 -0
  344. data/spec/support/retryable_writes_tests/insertOne.yml +9 -0
  345. data/spec/support/retryable_writes_tests/replaceOne-serverErrors.yml +58 -0
  346. data/spec/support/retryable_writes_tests/replaceOne.yml +9 -0
  347. data/spec/support/retryable_writes_tests/updateOne-serverErrors.yml +58 -0
  348. data/spec/support/retryable_writes_tests/updateOne.yml +71 -53
  349. data/spec/support/sdam/rs/normalize_case_me.yml +100 -0
  350. data/spec/support/sdam/sharded/compatible.yml +38 -0
  351. data/spec/support/sdam/sharded/mongos_disconnect.yml +9 -3
  352. data/spec/support/sdam/sharded/multiple_mongoses.yml +6 -2
  353. data/spec/support/sdam/sharded/non_mongos_removed.yml +6 -2
  354. data/spec/support/sdam/sharded/too_new.yml +36 -0
  355. data/spec/support/sdam/sharded/too_old.yml +36 -0
  356. data/spec/support/sdam/single/compatible.yml +26 -0
  357. data/spec/support/sdam/single/direct_connection_external_ip.yml +3 -1
  358. data/spec/support/sdam/single/direct_connection_mongos.yml +3 -1
  359. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +3 -1
  360. data/spec/support/sdam/single/direct_connection_rsprimary.yml +3 -1
  361. data/spec/support/sdam/single/direct_connection_rssecondary.yml +3 -1
  362. data/spec/support/sdam/single/direct_connection_slave.yml +3 -1
  363. data/spec/support/sdam/single/direct_connection_standalone.yml +3 -1
  364. data/spec/support/sdam/single/not_ok_response.yml +6 -2
  365. data/spec/support/sdam/single/standalone_removed.yml +3 -1
  366. data/spec/support/sdam/single/too_new.yml +26 -0
  367. data/spec/support/sdam/single/too_old.yml +24 -0
  368. data/spec/support/shared/session.rb +107 -0
  369. data/spec/support/transactions.rb +391 -0
  370. data/spec/support/transactions/operation.rb +373 -0
  371. data/spec/support/transactions_tests/abort.yml +403 -0
  372. data/spec/support/transactions_tests/bulk.yml +267 -0
  373. data/spec/support/transactions_tests/causal-consistency.yml +173 -0
  374. data/spec/support/transactions_tests/commit.yml +593 -0
  375. data/spec/support/transactions_tests/delete.yml +184 -0
  376. data/spec/support/transactions_tests/error-labels.yml +948 -0
  377. data/spec/support/transactions_tests/errors.yml +125 -0
  378. data/spec/support/transactions_tests/findOneAndDelete.yml +126 -0
  379. data/spec/support/transactions_tests/findOneAndReplace.yml +140 -0
  380. data/spec/support/transactions_tests/findOneAndUpdate.yml +228 -0
  381. data/spec/support/transactions_tests/insert.yml +264 -0
  382. data/spec/support/transactions_tests/isolation.yml +125 -0
  383. data/spec/support/transactions_tests/read-pref.yml +340 -0
  384. data/spec/support/transactions_tests/reads.yml +298 -0
  385. data/spec/support/transactions_tests/retryable-abort.yml +1292 -0
  386. data/spec/support/transactions_tests/retryable-commit.yml +1332 -0
  387. data/spec/support/transactions_tests/retryable-writes.yml +208 -0
  388. data/spec/support/transactions_tests/run-command.yml +189 -0
  389. data/spec/support/transactions_tests/transaction-options.yml +877 -0
  390. data/spec/support/transactions_tests/update.yml +246 -0
  391. data/spec/support/transactions_tests/write-concern.yml +236 -0
  392. metadata +494 -359
  393. metadata.gz.sig +0 -0
  394. data/lib/csasl/csasl.bundle +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2017 MongoDB, Inc.
1
+ # Copyright (C) 2017-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -24,32 +24,15 @@ module Mongo
24
24
 
25
25
  private
26
26
 
27
- RETRY_MESSAGES = [
28
- 'not master',
29
- '(43)' # cursor not found error code
30
- ].freeze
31
-
32
27
  def read_with_one_retry
33
28
  yield
34
- rescue => e
35
- if retryable?(e)
29
+ rescue Mongo::Error => e
30
+ if e.change_stream_resumable?
36
31
  yield
37
32
  else
38
33
  raise(e)
39
34
  end
40
35
  end
41
-
42
- def retryable?(error)
43
- network_error?(error) || retryable_operation_failure?(error)
44
- end
45
-
46
- def network_error?(error)
47
- [ Error::SocketError, Error::SocketTimeoutError].include?(error.class)
48
- end
49
-
50
- def retryable_operation_failure?(error)
51
- error.is_a?(Error::OperationFailure) && RETRY_MESSAGES.any? { |m| error.message.include?(m) }
52
- end
53
36
  end
54
37
  end
55
38
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ module Mongo
37
37
  def each
38
38
  @cursor = nil
39
39
  session = client.send(:get_session, @options)
40
- read_with_retry do
40
+ read_with_retry(session) do
41
41
  server = server_selector.select_server(cluster)
42
42
  result = send_initial_query(server, session)
43
43
  @cursor = Cursor.new(view, result, server, session: session)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -112,12 +112,12 @@ module Mongo
112
112
  # @example Get the number of documents in the collection.
113
113
  # collection_view.count
114
114
  #
115
- # @param [ Hash ] opts Options for the count command.
115
+ # @param [ Hash ] opts Options for the operation.
116
116
  #
117
117
  # @option opts :skip [ Integer ] The number of documents to skip.
118
118
  # @option opts :hint [ Hash ] Override default index selection and force
119
119
  # MongoDB to use a specific index for the query.
120
- # @option opts :limit [ Integer ] Max number of docs to return.
120
+ # @option opts :limit [ Integer ] Max number of docs to count.
121
121
  # @option opts :max_time_ms [ Integer ] The maximum amount of time to allow the
122
122
  # command to run.
123
123
  # @option opts [ Hash ] :read The read preference options.
@@ -126,6 +126,12 @@ module Mongo
126
126
  # @return [ Integer ] The document count.
127
127
  #
128
128
  # @since 2.0.0
129
+ #
130
+ # @deprecated Use #count_documents or #estimated_document_count instead. However, note that
131
+ # the following operators will need to be substituted when switching to #count_documents:
132
+ # * $where should be replaced with $expr (only works on 3.6+)
133
+ # * $near should be replaced with $geoWithin with $center
134
+ # * $nearSphere should be replaced with $geoWithin with $centerSphere
129
135
  def count(opts = {})
130
136
  cmd = { :count => collection.name, :query => filter }
131
137
  cmd[:skip] = opts[:skip] if opts[:skip]
@@ -135,10 +141,10 @@ module Mongo
135
141
  cmd[:readConcern] = collection.read_concern if collection.read_concern
136
142
  read_pref = opts[:read] || read_preference
137
143
  selector = ServerSelector.get(read_pref || server_selector)
138
- read_with_retry do
139
- server = selector.select_server(cluster)
140
- apply_collation!(cmd, server, opts)
141
- with_session(opts) do |session|
144
+ with_session(opts) do |session|
145
+ read_with_retry(session) do
146
+ server = selector.select_server(cluster)
147
+ apply_collation!(cmd, server, opts)
142
148
  Operation::Count.new({
143
149
  :selector => cmd,
144
150
  :db_name => database.name,
@@ -146,10 +152,71 @@ module Mongo
146
152
  :read => read_pref,
147
153
  :session => session
148
154
  }).execute(server)
149
- end.n.to_i
155
+ end.n.to_i
150
156
  end
151
157
  end
152
158
 
159
+ # Get a count of matching documents in the collection.
160
+ #
161
+ # @example Get the number of documents in the collection.
162
+ # collection_view.count
163
+ #
164
+ # @param [ Hash ] opts Options for the operation.
165
+ #
166
+ # @option opts :skip [ Integer ] The number of documents to skip.
167
+ # @option opts :hint [ Hash ] Override default index selection and force
168
+ # MongoDB to use a specific index for the query. Requires server version 3.6+.
169
+ # @option opts :limit [ Integer ] Max number of docs to count.
170
+ # @option opts :max_time_ms [ Integer ] The maximum amount of time to allow the
171
+ # command to run.
172
+ # @option opts [ Hash ] :read The read preference options.
173
+ # @option opts [ Hash ] :collation The collation to use.
174
+ #
175
+ # @return [ Integer ] The document count.
176
+ #
177
+ # @since 2.6.0
178
+ def count_documents(opts = {})
179
+ pipeline = [:'$match' => filter]
180
+ pipeline << { :'$skip' => opts[:skip] } if opts[:skip]
181
+ pipeline << { :'$limit' => opts[:limit] } if opts[:limit]
182
+ pipeline << { :'$group' => { _id: nil, n: { :'$sum' => 1 } } }
183
+
184
+ opts.select! { |k, _| [:hint, :max_time_ms, :read, :collation].include?(k) }
185
+ aggregate(pipeline, opts).first['n'].to_i
186
+ end
187
+
188
+ # Gets an estimate of the count of documents in a collection using collection metadata.
189
+ #
190
+ # @example Get the number of documents in the collection.
191
+ # collection_view.estimated_document_count
192
+ #
193
+ # @param [ Hash ] opts Options for the operation.
194
+ #
195
+ # @option opts :max_time_ms [ Integer ] The maximum amount of time to allow the command to
196
+ # run.
197
+ # @option opts [ Hash ] :read The read preference options.
198
+ #
199
+ # @return [ Integer ] The document count.
200
+ #
201
+ # @since 2.6.0
202
+ def estimated_document_count(opts = {})
203
+ cmd = { count: collection.name }
204
+ cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
205
+ cmd[:readConcern] = collection.read_concern if collection.read_concern
206
+ read_pref = opts[:read] || read_preference
207
+ selector = ServerSelector.get(read_pref || server_selector)
208
+ with_session(opts) do |session|
209
+ read_with_retry(session) do
210
+ server = selector.select_server(cluster)
211
+ Operation::Count.new(
212
+ selector: cmd,
213
+ db_name: database.name,
214
+ read: read_pref,
215
+ session: session
216
+ ).execute(server)
217
+ end.n.to_i
218
+ end
219
+ end
153
220
 
154
221
  # Get a list of distinct values for a specific field.
155
222
  #
@@ -175,10 +242,10 @@ module Mongo
175
242
  cmd[:readConcern] = collection.read_concern if collection.read_concern
176
243
  read_pref = opts[:read] || read_preference
177
244
  selector = ServerSelector.get(read_pref || server_selector)
178
- read_with_retry do
179
- server = selector.select_server(cluster)
180
- apply_collation!(cmd, server, opts)
181
- with_session(opts) do |session|
245
+ with_session(opts) do |session|
246
+ read_with_retry(session) do
247
+ server = selector.select_server(cluster)
248
+ apply_collation!(cmd, server, opts)
182
249
  Operation::Distinct.new({
183
250
  :selector => cmd,
184
251
  :db_name => database.name,
@@ -470,38 +537,50 @@ module Mongo
470
537
  end
471
538
 
472
539
  def read_preference
473
- @read_preference ||= (options[:read] || collection.read_preference)
540
+ if options[:session] && options[:session].in_transaction?
541
+ options[:session].send(:txn_read_pref) || collection.client.read_preference
542
+ else
543
+ @read_preference ||= (options[:read] || collection.read_preference)
544
+ end
474
545
  end
475
546
 
476
547
  def server_selector
477
- @server_selector ||= ServerSelector.get(read_preference || collection.server_selector)
548
+ if options[:session] && options[:session].in_transaction?
549
+ ServerSelector.get(read_preference || client.server_selector)
550
+ else
551
+ @server_selector ||= ServerSelector.get(read_preference || collection.server_selector)
552
+ end
478
553
  end
479
554
 
480
555
  def parallel_scan(cursor_count, options = {})
481
- session = client.send(:get_session, @options)
556
+ if options[:session]
557
+ session = client.send(:get_session, @options)
558
+ else
559
+ session = nil
560
+ end
482
561
  server = server_selector.select_server(cluster)
483
562
  cmd = Operation::ParallelScan.new({
484
563
  :coll_name => collection.name,
485
564
  :db_name => database.name,
486
565
  :cursor_count => cursor_count,
487
566
  :read_concern => collection.read_concern,
488
- :session => session
567
+ :session => session,
489
568
  }.merge!(options))
490
569
  cmd.execute(server).cursor_ids.map do |cursor_id|
491
570
  result = if server.features.find_command_enabled?
492
- Operation::GetMore.new({
493
- :selector => {:getMore => cursor_id,
494
- :collection => collection.name},
495
- :db_name => database.name,
496
- :session => session
497
- }).execute(server)
498
- else
499
- Operation::GetMore.new({
500
- :to_return => 0,
501
- :cursor_id => cursor_id,
502
- :db_name => database.name,
503
- :coll_name => collection.name
504
- }).execute(server)
571
+ Operation::GetMore.new({
572
+ :selector => {:getMore => cursor_id,
573
+ :collection => collection.name},
574
+ :db_name => database.name,
575
+ :session => session,
576
+ }).execute(server)
577
+ else
578
+ Operation::GetMore.new({
579
+ :to_return => 0,
580
+ :cursor_id => cursor_id,
581
+ :db_name => database.name,
582
+ :coll_name => collection.name
583
+ }).execute(server)
505
584
  end
506
585
  Cursor.new(self, result, server, session: session)
507
586
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ module Mongo
40
40
  #
41
41
  # @since 2.0.0
42
42
  def find_one_and_delete(opts = {})
43
- cmd = { :findandmodify => collection.name, :query => filter, :remove => true }
43
+ cmd = { :findAndModify => collection.name, :query => filter, :remove => true }
44
44
  cmd[:fields] = projection if projection
45
45
  cmd[:sort] = sort if sort
46
46
  cmd[:maxTimeMS] = max_time_ms if max_time_ms
@@ -107,7 +107,7 @@ module Mongo
107
107
  #
108
108
  # @since 2.0.0
109
109
  def find_one_and_update(document, opts = {})
110
- cmd = { :findandmodify => collection.name, :query => filter }
110
+ cmd = { :findAndModify => collection.name, :query => filter }
111
111
  cmd[:update] = document
112
112
  cmd[:fields] = projection if projection
113
113
  cmd[:sort] = sort if sort
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -52,8 +52,8 @@ module Mongo
52
52
  # @param [ Server ] server The server this cursor is locked to.
53
53
  # @param [ Hash ] options The cursor options.
54
54
  #
55
- # @option options [ true, false ] :disable_retry Whether to disable retrying on
56
- # error when sending getmores.
55
+ # @option options [ true, false ] :disable_retry Whether to disable
56
+ # retrying on error when sending getMores.
57
57
  #
58
58
  # @since 2.0.0
59
59
  def initialize(view, result, server, options = {})
@@ -125,6 +125,46 @@ module Mongo
125
125
  end
126
126
  end
127
127
 
128
+ # Return one document from the query, if one is available.
129
+ #
130
+ # Retries once on a resumable error.
131
+ #
132
+ # This method will wait up to max_await_time_ms milliseconds
133
+ # for changes from the server, and if no changes are received
134
+ # it will return nil.
135
+ #
136
+ # @note This method is experimental and subject to change.
137
+ #
138
+ # @return [ BSON::Document | nil ] A document.
139
+ # @api private
140
+ def try_next
141
+ if @documents.nil?
142
+ @documents = process(@initial_result)
143
+ # the documents here can be an empty array, hence
144
+ # we may end up issuing a getMore in the first try_next call
145
+ end
146
+
147
+ if @documents.empty?
148
+ if more?
149
+ if exhausted?
150
+ kill_cursors
151
+ return nil
152
+ end
153
+
154
+ @documents = get_more
155
+ end
156
+ else
157
+ # cursor is closed here
158
+ # keep documents as an empty array
159
+ end
160
+
161
+ if @documents
162
+ return @documents.shift
163
+ end
164
+
165
+ nil
166
+ end
167
+
128
168
  # Get the batch size.
129
169
  #
130
170
  # @example Get the batch size.
@@ -198,7 +238,7 @@ module Mongo
198
238
  if @options[:disable_retry]
199
239
  process(get_more_operation.execute(@server))
200
240
  else
201
- read_with_retry do
241
+ read_with_retry(@session) do
202
242
  process(get_more_operation.execute(@server))
203
243
  end
204
244
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2017 MongoDB, Inc.
1
+ # Copyright (C) 2015-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2017 MongoDB, Inc.
1
+ # Copyright (C) 2015-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2017 MongoDB, Inc.
1
+ # Copyright (C) 2015-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2017 MongoDB, Inc.
1
+ # Copyright (C) 2015-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015-2017 MongoDB, Inc.
1
+ # Copyright (C) 2015-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 MongoDB, Inc.
1
+ # Copyright (C) 2014-2018 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -105,7 +105,7 @@ module Mongo
105
105
  end
106
106
  alias_method :collection, :[]
107
107
 
108
- # Get all the names of the non system collections in the database.
108
+ # Get all the names of the non-system collections in the database.
109
109
  #
110
110
  # @example Get the collection names.
111
111
  # database.collection_names
@@ -153,8 +153,10 @@ module Mongo
153
153
  #
154
154
  # @return [ Hash ] The result of the command execution.
155
155
  def command(operation, opts = {})
156
- preference = ServerSelector.get(opts[:read] || ServerSelector::PRIMARY)
156
+ txn_read_pref = opts[:session] && opts[:session].in_transaction? && opts[:session].txn_read_pref
157
+ preference = ServerSelector.get(txn_read_pref || opts[:read] || ServerSelector::PRIMARY)
157
158
  server = preference.select_server(cluster)
159
+
158
160
  client.send(:with_session, opts) do |session|
159
161
  Operation::Command.new({
160
162
  :selector => operation.dup,
@@ -244,6 +246,47 @@ module Mongo
244
246
  Auth::User::View.new(self)
245
247
  end
246
248
 
249
+ # As of version 3.6 of the MongoDB server, a ``$changeStream`` pipeline stage is supported
250
+ # in the aggregation framework. As of version 4.0, this stage allows users to request that
251
+ # notifications are sent for all changes that occur in the client's database.
252
+ #
253
+ # @example Get change notifications for a given database..
254
+ # database.watch([{ '$match' => { operationType: { '$in' => ['insert', 'replace'] } } }])
255
+ #
256
+ # @param [ Array<Hash> ] pipeline Optional additional filter operators.
257
+ # @param [ Hash ] options The change stream options.
258
+ #
259
+ # @option options [ String ] :full_document Allowed values: 'default', 'updateLookup'.
260
+ # Defaults to 'default'. When set to 'updateLookup', the change notification for partial
261
+ # updates will include both a delta describing the changes to the document, as well as a copy
262
+ # of the entire document that was changed from some time after the change occurred.
263
+ # @option options [ BSON::Document, Hash ] :resume_after Specifies the logical starting point
264
+ # for the new change stream.
265
+ # @option options [ Integer ] :max_await_time_ms The maximum amount of time for the server to
266
+ # wait on new documents to satisfy a change stream query.
267
+ # @option options [ Integer ] :batch_size The number of documents to return per batch.
268
+ # @option options [ BSON::Document, Hash ] :collation The collation to use.
269
+ # @option options [ Session ] :session The session to use.
270
+ # @option options [ BSON::Timestamp ] :start_at_operation_time Only return
271
+ # changes that occurred after the specified timestamp. Any command run
272
+ # against the server will return a cluster time that can be used here.
273
+ # Only recognized by server versions 4.0+.
274
+ #
275
+ # @note A change stream only allows 'majority' read concern.
276
+ # @note This helper method is preferable to running a raw aggregation with a $changeStream
277
+ # stage, for the purpose of supporting resumability.
278
+ #
279
+ # @return [ ChangeStream ] The change stream object.
280
+ #
281
+ # @since 2.6.0
282
+ def watch(pipeline = [], options = {})
283
+ Mongo::Collection::View::ChangeStream.new(
284
+ Mongo::Collection::View.new(collection("#{COMMAND}.aggregate")),
285
+ pipeline,
286
+ Mongo::Collection::View::ChangeStream::DATABASE,
287
+ options)
288
+ end
289
+
247
290
  # Create a database for the provided client, for use when we don't want the
248
291
  # client's original database instance to be the same.
249
292
  #