mongo 2.15.0 → 2.17.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 (393) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/lib/mongo/auth/aws/request.rb +0 -1
  5. data/lib/mongo/bulk_write.rb +2 -2
  6. data/lib/mongo/client.rb +49 -5
  7. data/lib/mongo/cluster/periodic_executor.rb +4 -3
  8. data/lib/mongo/cluster/reapers/cursor_reaper.rb +76 -43
  9. data/lib/mongo/cluster/sdam_flow.rb +9 -3
  10. data/lib/mongo/cluster/topology/base.rb +13 -9
  11. data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
  12. data/lib/mongo/cluster/topology.rb +28 -8
  13. data/lib/mongo/cluster.rb +136 -51
  14. data/lib/mongo/collection/view/aggregation.rb +63 -23
  15. data/lib/mongo/collection/view/builder/aggregation.rb +16 -17
  16. data/lib/mongo/collection/view/builder/map_reduce.rb +12 -49
  17. data/lib/mongo/collection/view/builder.rb +0 -4
  18. data/lib/mongo/collection/view/change_stream.rb +7 -3
  19. data/lib/mongo/collection/view/iterable.rb +60 -27
  20. data/lib/mongo/collection/view/map_reduce.rb +41 -15
  21. data/lib/mongo/collection/view/readable.rb +84 -52
  22. data/lib/mongo/collection/view/writable.rb +201 -175
  23. data/lib/mongo/collection/view.rb +15 -21
  24. data/lib/mongo/collection.rb +34 -14
  25. data/lib/mongo/cursor/kill_spec.rb +38 -0
  26. data/lib/mongo/cursor.rb +72 -31
  27. data/lib/mongo/database/view.rb +5 -3
  28. data/lib/mongo/database.rb +6 -6
  29. data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
  30. data/lib/mongo/error/missing_service_id.rb +26 -0
  31. data/lib/mongo/error/no_service_connection_available.rb +49 -0
  32. data/lib/mongo/error/notable.rb +7 -0
  33. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
  34. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
  35. data/lib/mongo/error.rb +5 -0
  36. data/lib/mongo/grid/fs_bucket.rb +21 -2
  37. data/lib/mongo/id.rb +7 -5
  38. data/lib/mongo/index/view.rb +22 -41
  39. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +7 -4
  40. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  41. data/lib/mongo/monitoring/event/command_started.rb +2 -0
  42. data/lib/mongo/monitoring/publishable.rb +2 -2
  43. data/lib/mongo/operation/aggregate/command.rb +8 -0
  44. data/lib/mongo/operation/context.rb +19 -1
  45. data/lib/mongo/operation/count/command.rb +6 -0
  46. data/lib/mongo/operation/count/op_msg.rb +6 -0
  47. data/lib/mongo/operation/create/command.rb +7 -1
  48. data/lib/mongo/operation/create/op_msg.rb +7 -0
  49. data/lib/mongo/operation/create_index/command.rb +17 -1
  50. data/lib/mongo/operation/create_index/op_msg.rb +17 -4
  51. data/lib/mongo/operation/delete/command.rb +6 -3
  52. data/lib/mongo/operation/delete/legacy.rb +9 -2
  53. data/lib/mongo/operation/delete/op_msg.rb +9 -1
  54. data/lib/mongo/operation/distinct/command.rb +6 -0
  55. data/lib/mongo/operation/distinct/op_msg.rb +7 -0
  56. data/lib/mongo/operation/explain/command.rb +13 -1
  57. data/lib/mongo/operation/explain/legacy.rb +12 -5
  58. data/lib/mongo/operation/explain/op_msg.rb +9 -1
  59. data/lib/mongo/operation/find/builder/command.rb +111 -0
  60. data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +10 -14
  61. data/lib/mongo/operation/find/builder/legacy.rb +123 -0
  62. data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +31 -25
  63. data/lib/mongo/{cursor → operation/find}/builder.rb +4 -4
  64. data/lib/mongo/operation/find/command.rb +9 -0
  65. data/lib/mongo/operation/find/legacy.rb +10 -1
  66. data/lib/mongo/operation/find/op_msg.rb +12 -0
  67. data/lib/mongo/operation/find.rb +1 -0
  68. data/lib/mongo/operation/get_more/command.rb +1 -0
  69. data/lib/mongo/operation/get_more/command_builder.rb +38 -0
  70. data/lib/mongo/operation/get_more/op_msg.rb +1 -0
  71. data/lib/mongo/operation/get_more.rb +1 -0
  72. data/lib/mongo/operation/kill_cursors/command.rb +8 -0
  73. data/lib/mongo/operation/kill_cursors/command_builder.rb +35 -0
  74. data/lib/mongo/operation/kill_cursors/legacy.rb +2 -1
  75. data/lib/mongo/operation/kill_cursors/op_msg.rb +10 -0
  76. data/lib/mongo/operation/kill_cursors.rb +1 -0
  77. data/lib/mongo/operation/map_reduce/command.rb +8 -0
  78. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  79. data/lib/mongo/operation/result.rb +6 -0
  80. data/lib/mongo/operation/shared/executable.rb +19 -1
  81. data/lib/mongo/operation/shared/polymorphic_operation.rb +1 -1
  82. data/lib/mongo/operation/shared/read_preference_supported.rb +3 -1
  83. data/lib/mongo/operation/shared/response_handling.rb +1 -0
  84. data/lib/mongo/operation/shared/sessions_supported.rb +28 -12
  85. data/lib/mongo/operation/shared/specifiable.rb +11 -29
  86. data/lib/mongo/operation/shared/validatable.rb +87 -0
  87. data/lib/mongo/operation/shared/write.rb +1 -1
  88. data/lib/mongo/operation/update/command.rb +6 -3
  89. data/lib/mongo/operation/update/legacy.rb +19 -11
  90. data/lib/mongo/operation/update/op_msg.rb +8 -4
  91. data/lib/mongo/operation/write_command/command.rb +51 -0
  92. data/lib/mongo/operation/write_command/op_msg.rb +43 -0
  93. data/lib/mongo/operation/write_command.rb +32 -0
  94. data/lib/mongo/operation.rb +10 -0
  95. data/lib/mongo/protocol/query.rb +35 -18
  96. data/lib/mongo/server/connection.rb +25 -3
  97. data/lib/mongo/server/connection_base.rb +12 -1
  98. data/lib/mongo/server/connection_common.rb +38 -1
  99. data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
  100. data/lib/mongo/server/connection_pool.rb +100 -27
  101. data/lib/mongo/server/description/features.rb +20 -17
  102. data/lib/mongo/server/description/load_balancer.rb +33 -0
  103. data/lib/mongo/server/description.rb +85 -6
  104. data/lib/mongo/server/monitor/connection.rb +5 -6
  105. data/lib/mongo/server/monitor.rb +2 -1
  106. data/lib/mongo/server/pending_connection.rb +47 -31
  107. data/lib/mongo/server/push_monitor.rb +10 -1
  108. data/lib/mongo/server.rb +73 -26
  109. data/lib/mongo/server_selector/base.rb +31 -5
  110. data/lib/mongo/session/session_pool.rb +11 -0
  111. data/lib/mongo/session.rb +40 -1
  112. data/lib/mongo/socket/ocsp_cache.rb +2 -3
  113. data/lib/mongo/socket/ocsp_verifier.rb +6 -37
  114. data/lib/mongo/socket.rb +1 -5
  115. data/lib/mongo/uri/options_mapper.rb +1 -0
  116. data/lib/mongo/uri/srv_protocol.rb +6 -8
  117. data/lib/mongo/uri.rb +18 -0
  118. data/lib/mongo/utils.rb +0 -13
  119. data/lib/mongo/version.rb +1 -1
  120. data/mongo.gemspec +1 -1
  121. data/spec/integration/auth_spec.rb +31 -1
  122. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  123. data/spec/integration/bulk_write_spec.rb +1 -1
  124. data/spec/integration/change_stream_spec.rb +3 -3
  125. data/spec/integration/client_construction_spec.rb +54 -0
  126. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  127. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  128. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  129. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  130. data/spec/integration/client_spec.rb +2 -0
  131. data/spec/integration/command_monitoring_spec.rb +1 -1
  132. data/spec/integration/command_spec.rb +1 -1
  133. data/spec/integration/connection_spec.rb +52 -35
  134. data/spec/integration/crud_spec.rb +174 -1
  135. data/spec/integration/cursor_pinning_spec.rb +121 -0
  136. data/spec/integration/cursor_reaping_spec.rb +8 -4
  137. data/spec/integration/fork_reconnect_spec.rb +1 -5
  138. data/spec/integration/get_more_spec.rb +1 -1
  139. data/spec/integration/heartbeat_events_spec.rb +1 -1
  140. data/spec/integration/map_reduce_spec.rb +77 -0
  141. data/spec/integration/query_cache_spec.rb +47 -2
  142. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  143. data/spec/integration/read_concern_spec.rb +1 -1
  144. data/spec/integration/read_preference_spec.rb +17 -13
  145. data/spec/integration/reconnect_spec.rb +30 -12
  146. data/spec/integration/retryable_errors_spec.rb +1 -1
  147. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  148. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  149. data/spec/integration/sdam_error_handling_spec.rb +5 -3
  150. data/spec/integration/sdam_events_spec.rb +35 -19
  151. data/spec/integration/sdam_prose_spec.rb +1 -1
  152. data/spec/integration/server_monitor_spec.rb +1 -0
  153. data/spec/integration/server_selector_spec.rb +22 -5
  154. data/spec/integration/server_spec.rb +2 -0
  155. data/spec/integration/srv_monitoring_spec.rb +1 -1
  156. data/spec/integration/step_down_spec.rb +1 -1
  157. data/spec/integration/transaction_pinning_spec.rb +120 -0
  158. data/spec/integration/versioned_api_examples_spec.rb +45 -0
  159. data/spec/integration/x509_auth_spec.rb +1 -1
  160. data/spec/lite_spec_helper.rb +1 -2
  161. data/spec/mongo/address/unix_spec.rb +1 -0
  162. data/spec/mongo/auth/cr_spec.rb +2 -3
  163. data/spec/mongo/auth/ldap_spec.rb +2 -3
  164. data/spec/mongo/auth/scram_spec.rb +2 -3
  165. data/spec/mongo/auth/user/view_spec.rb +1 -1
  166. data/spec/mongo/auth/x509_spec.rb +2 -3
  167. data/spec/mongo/bulk_write_spec.rb +3 -3
  168. data/spec/mongo/client_construction_spec.rb +259 -28
  169. data/spec/mongo/client_spec.rb +6 -4
  170. data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
  171. data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
  172. data/spec/mongo/cluster_spec.rb +44 -3
  173. data/spec/mongo/collection/view/aggregation_spec.rb +72 -96
  174. data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
  175. data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
  176. data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
  177. data/spec/mongo/collection/view/map_reduce_spec.rb +15 -2
  178. data/spec/mongo/collection_crud_spec.rb +7 -2
  179. data/spec/mongo/collection_ddl_spec.rb +1 -1
  180. data/spec/mongo/collection_spec.rb +1 -1
  181. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
  182. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
  183. data/spec/mongo/cursor_spec.rb +15 -5
  184. data/spec/mongo/database_spec.rb +15 -15
  185. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  186. data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
  187. data/spec/mongo/grid/stream/write_spec.rb +3 -9
  188. data/spec/mongo/grid/stream_spec.rb +1 -1
  189. data/spec/mongo/index/view_spec.rb +2 -2
  190. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  191. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
  192. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
  193. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  194. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  195. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  196. data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
  197. data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
  198. data/spec/mongo/operation/read_preference_op_msg_spec.rb +26 -1
  199. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  200. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  201. data/spec/mongo/query_cache_spec.rb +6 -2
  202. data/spec/mongo/server/connection_common_spec.rb +62 -11
  203. data/spec/mongo/server/connection_pool_spec.rb +73 -7
  204. data/spec/mongo/server/connection_spec.rb +138 -43
  205. data/spec/mongo/server/description_spec.rb +1 -1
  206. data/spec/mongo/server/monitor/connection_spec.rb +22 -0
  207. data/spec/mongo/server/monitor_spec.rb +4 -3
  208. data/spec/mongo/server/push_monitor_spec.rb +101 -0
  209. data/spec/mongo/server_selector_spec.rb +136 -15
  210. data/spec/mongo/session/session_pool_spec.rb +42 -10
  211. data/spec/mongo/session_transaction_spec.rb +15 -30
  212. data/spec/mongo/socket/ssl_spec.rb +26 -58
  213. data/spec/mongo/socket/unix_spec.rb +1 -0
  214. data/spec/mongo/uri_option_parsing_spec.rb +38 -5
  215. data/spec/mongo/utils_spec.rb +0 -14
  216. data/spec/runners/change_streams/test.rb +1 -1
  217. data/spec/runners/cmap.rb +1 -1
  218. data/spec/runners/connection_string.rb +7 -3
  219. data/spec/runners/crud/operation.rb +5 -3
  220. data/spec/runners/crud/requirement.rb +1 -0
  221. data/spec/runners/crud/verifier.rb +1 -2
  222. data/spec/runners/crud.rb +1 -1
  223. data/spec/runners/sdam.rb +2 -1
  224. data/spec/runners/transactions/test.rb +2 -2
  225. data/spec/runners/unified/assertions.rb +5 -4
  226. data/spec/runners/unified/crud_operations.rb +77 -23
  227. data/spec/runners/unified/ddl_operations.rb +29 -1
  228. data/spec/runners/unified/entity_map.rb +3 -3
  229. data/spec/runners/unified/event_subscriber.rb +2 -2
  230. data/spec/runners/unified/support_operations.rb +16 -3
  231. data/spec/runners/unified/test.rb +18 -3
  232. data/spec/runners/unified.rb +1 -1
  233. data/spec/shared/lib/mrss/cluster_config.rb +6 -1
  234. data/spec/shared/lib/mrss/constraints.rb +11 -5
  235. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  236. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  237. data/spec/shared/share/Dockerfile.erb +5 -4
  238. data/spec/shared/shlib/server.sh +70 -20
  239. data/spec/spec_tests/change_streams_spec.rb +1 -1
  240. data/spec/spec_tests/cmap_spec.rb +4 -1
  241. data/spec/spec_tests/command_monitoring_spec.rb +2 -2
  242. data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
  243. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  244. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  245. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  246. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  247. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  248. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  249. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  250. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  251. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  252. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  253. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  254. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  255. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  256. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  257. data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
  258. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
  259. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
  260. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
  261. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
  262. data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
  263. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
  264. data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
  265. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
  266. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
  267. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
  268. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  269. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  270. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  271. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  272. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
  273. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  274. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  275. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  276. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
  277. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
  278. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
  279. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
  280. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
  281. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
  282. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
  283. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
  284. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
  285. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  288. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  289. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  290. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
  291. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  292. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
  293. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
  294. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  295. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
  296. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  297. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
  298. data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
  299. data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
  300. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
  301. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
  302. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  303. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
  304. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  305. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
  306. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  307. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
  308. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  309. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
  310. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
  311. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
  312. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
  313. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
  314. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
  315. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
  316. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  317. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  318. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  319. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  320. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  321. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
  322. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
  323. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  324. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  325. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  326. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  327. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  328. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  329. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  330. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  331. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  332. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  333. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  334. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  335. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  336. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  337. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  338. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  339. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  340. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  341. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  342. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  343. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  344. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  345. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  346. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  347. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  348. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  349. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
  350. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
  351. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
  352. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
  353. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
  354. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
  355. data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
  356. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
  357. data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
  358. data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
  359. data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
  360. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  361. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  362. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  363. data/spec/spec_tests/sdam_integration_spec.rb +1 -1
  364. data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
  365. data/spec/spec_tests/sdam_spec.rb +1 -1
  366. data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
  367. data/spec/spec_tests/sessions_unified_spec.rb +13 -0
  368. data/spec/spec_tests/uri_options_spec.rb +4 -4
  369. data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
  370. data/spec/stress/push_monitor_close_spec.rb +44 -0
  371. data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
  372. data/spec/support/certificates/atlas-ocsp.crt +127 -122
  373. data/spec/support/common_shortcuts.rb +2 -3
  374. data/spec/support/matchers.rb +13 -0
  375. data/spec/support/shared/auth_context.rb +16 -0
  376. data/spec/support/shared/session.rb +2 -2
  377. data/spec/support/spec_config.rb +10 -11
  378. data/spec/support/using_hash.rb +31 -0
  379. data/spec/support/utils.rb +1 -1
  380. data.tar.gz.sig +3 -4
  381. metadata +1111 -1029
  382. metadata.gz.sig +2 -3
  383. data/lib/mongo/collection/view/builder/find_command.rb +0 -173
  384. data/lib/mongo/collection/view/builder/op_query.rb +0 -94
  385. data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
  386. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
  387. data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
  388. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
  389. data/lib/mongo/server/context.rb +0 -72
  390. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
  391. data/spec/runners/unified/using_hash.rb +0 -34
  392. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
  393. data/spec/support/event_subscriber.rb +0 -221
@@ -80,7 +80,7 @@ module Mongo
80
80
  DOT_PARTITION = '.'.freeze
81
81
 
82
82
  # @return [ Array<String> ] VALID_TXT_OPTIONS The valid options for a TXT record to specify.
83
- VALID_TXT_OPTIONS = ['replicaset', 'authsource'].freeze
83
+ VALID_TXT_OPTIONS = %w(replicaset authsource loadbalanced).freeze
84
84
 
85
85
  # @return [ String ] INVALID_HOST Error message format string indicating that the hostname in
86
86
  # in the URI does not fit the expected form.
@@ -102,11 +102,6 @@ module Mongo
102
102
  # were found.
103
103
  NO_SRV_RECORDS = "The DNS query returned no SRV records for '%s'".freeze
104
104
 
105
- # @return [ String ] INVALID_TXT_RECORD_OPTION Error message format string indicating that an
106
- # unexpected TXT record option was found.
107
- INVALID_TXT_RECORD_OPTION = "TXT records can only specify the options " +
108
- "[#{VALID_TXT_OPTIONS.join(', ')}].".freeze
109
-
110
105
  # @return [ String ] FORMAT The expected SRV URI format.
111
106
  FORMAT = 'mongodb+srv://[username:password@]host[/[database][?options]]'.freeze
112
107
 
@@ -222,8 +217,11 @@ module Mongo
222
217
  def parse_txt_options!(string)
223
218
  string.split(INDIV_URI_OPTS_DELIM).reduce({}) do |txt_options, opt|
224
219
  raise Error::InvalidTXTRecord.new(INVALID_OPTS_VALUE_DELIM) unless opt.index(URI_OPTS_VALUE_DELIM)
225
- key, value = opt.split(URI_OPTS_VALUE_DELIM)
226
- raise Error::InvalidTXTRecord.new(INVALID_TXT_RECORD_OPTION) unless VALID_TXT_OPTIONS.include?(key.downcase)
220
+ key, value = opt.split('=')
221
+ unless VALID_TXT_OPTIONS.include?(key.downcase)
222
+ msg = "TXT records can only specify the options [#{VALID_TXT_OPTIONS.join(', ')}]: #{string}"
223
+ raise Error::InvalidTXTRecord.new(msg)
224
+ end
227
225
  options_mapper.add_uri_option(key, value, txt_options)
228
226
  txt_options
229
227
  end
data/lib/mongo/uri.rb CHANGED
@@ -520,6 +520,24 @@ module Mongo
520
520
  elsif uri_options[:direct_connection] == false && uri_options[:connect].to_s == 'direct'
521
521
  raise_invalid_error_no_fmt!("directConnection=false cannot be used with connect=direct")
522
522
  end
523
+
524
+ if uri_options[:load_balanced]
525
+ if servers.length > 1
526
+ raise_invalid_error_no_fmt!("loadBalanced=true cannot be used with multiple seeds")
527
+ end
528
+
529
+ if uri_options[:direct_connection]
530
+ raise_invalid_error_no_fmt!("directConnection=true cannot be used with loadBalanced=true")
531
+ end
532
+
533
+ if uri_options[:connect] && uri_options[:connect].to_sym == :direct
534
+ raise_invalid_error_no_fmt!("connect=direct cannot be used with loadBalanced=true")
535
+ end
536
+
537
+ if uri_options[:replica_set]
538
+ raise_invalid_error_no_fmt!("loadBalanced=true cannot be used with replicaSet option")
539
+ end
540
+ end
523
541
  end
524
542
  end
525
543
  end
data/lib/mongo/utils.rb CHANGED
@@ -101,18 +101,5 @@ module Mongo
101
101
  module_function def monotonic_time
102
102
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
103
103
  end
104
-
105
- # Hash#compact implementation for Ruby 2.3
106
- module_function def compact_hash(hash)
107
- Hash[hash.reject do |k, v|
108
- v.nil?
109
- end]
110
- end
111
-
112
- # Hash#compact implementation for Ruby 2.3/2.4
113
- # Implementation based on activesupport 5.2.3
114
- module_function def slice_hash(hash, *keys)
115
- keys.each_with_object({}) { |k, res| res[k] = hash[k] if hash.key?(k) }
116
- end
117
104
  end
118
105
  end
data/lib/mongo/version.rb CHANGED
@@ -20,5 +20,5 @@ module Mongo
20
20
  # The current version of the driver.
21
21
  #
22
22
  # @since 2.0.0
23
- VERSION = '2.15.0'.freeze
23
+ VERSION = '2.17.0'.freeze
24
24
  end
data/mongo.gemspec CHANGED
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
36
36
  s.require_paths = ['lib']
37
37
  s.bindir = 'bin'
38
38
 
39
- s.required_ruby_version = ">= 2.3"
39
+ s.required_ruby_version = ">= 2.5"
40
40
 
41
41
  s.add_dependency 'bson', '>=4.8.2', '<5.0.0'
42
42
  end
@@ -14,7 +14,7 @@ describe 'Auth' do
14
14
  end
15
15
 
16
16
  let(:base_options) do
17
- SpecConfig.instance.monitoring_options
17
+ SpecConfig.instance.monitoring_options.merge(connect: SpecConfig.instance.test_options[:connect])
18
18
  end
19
19
 
20
20
  let(:connection) do
@@ -276,4 +276,34 @@ describe 'Auth' do
276
276
  client.database.command(ping: 1)
277
277
  end
278
278
  end
279
+
280
+ context 'in lb topology' do
281
+ require_topology :load_balanced
282
+
283
+ context 'when authentication fails with network error' do
284
+ let(:server) do
285
+ authorized_client.cluster.next_primary
286
+ end
287
+
288
+ let(:base_options) do
289
+ SpecConfig.instance.monitoring_options.merge(connect: SpecConfig.instance.test_options[:connect])
290
+ end
291
+
292
+ let(:connection) do
293
+ Mongo::Server::Connection.new(server, base_options)
294
+ end
295
+
296
+ it 'includes service id in exception' do
297
+ expect_any_instance_of(Mongo::Server::PendingConnection).to receive(:authenticate!).and_raise(Mongo::Error::SocketError)
298
+
299
+ begin
300
+ connection.connect!
301
+ rescue Mongo::Error::SocketError => exc
302
+ exc.service_id.should_not be nil
303
+ else
304
+ fail 'Expected the SocketError to be raised'
305
+ end
306
+ end
307
+ end
308
+ end
279
309
  end
@@ -9,7 +9,7 @@ describe 'awaited hello' do
9
9
  # If we send the consecutive hello commands to different mongoses,
10
10
  # they have different process ids, and so the awaited one would return
11
11
  # immediately.
12
- require_no_multi_shard
12
+ require_no_multi_mongos
13
13
 
14
14
  let(:client) { authorized_client }
15
15
 
@@ -21,7 +21,7 @@ describe 'Bulk writes' do
21
21
  end
22
22
 
23
23
  context 'when bulk write needs to be split' do
24
- let(:subscriber) { EventSubscriber.new }
24
+ let(:subscriber) { Mrss::EventSubscriber.new }
25
25
 
26
26
  let(:max_bson_size) { Mongo::Server::ConnectionBase::DEFAULT_MAX_BSON_OBJECT_SIZE }
27
27
 
@@ -53,7 +53,7 @@ describe 'Change stream integration', retry: 4 do
53
53
  it 'raises an exception and does not attempt to resume' do
54
54
  change_stream
55
55
 
56
- subscriber = EventSubscriber.new
56
+ subscriber = Mrss::EventSubscriber.new
57
57
  authorized_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
58
58
 
59
59
  expect do
@@ -523,7 +523,7 @@ describe 'Change stream integration', retry: 4 do
523
523
  let(:events) do
524
524
  start_after
525
525
 
526
- subscriber = EventSubscriber.new
526
+ subscriber = Mrss::EventSubscriber.new
527
527
  authorized_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
528
528
  use_stream
529
529
 
@@ -582,7 +582,7 @@ describe 'Change stream integration', retry: 4 do
582
582
  let(:stream) { authorized_collection.watch }
583
583
 
584
584
  let(:events) do
585
- subscriber = EventSubscriber.new
585
+ subscriber = Mrss::EventSubscriber.new
586
586
  authorized_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
587
587
  use_stream
588
588
  subscriber.succeeded_events.select { |e|
@@ -236,4 +236,58 @@ describe 'Client construction' do
236
236
  expect(client.cluster.addresses).to eq([Mongo::Address.new(primary_address)])
237
237
  end
238
238
  end
239
+
240
+ context 'when deployment is not a sharded cluster' do
241
+ require_topology :single, :replica_set
242
+
243
+ let(:client) do
244
+ ClientRegistry.instance.new_local_client(
245
+ [SpecConfig.instance.addresses.first],
246
+ SpecConfig.instance.test_options.merge(options),
247
+ )
248
+ end
249
+
250
+ context 'when load-balanced topology is requested' do
251
+ let(:options) do
252
+ {connect: :load_balanced, replica_set: nil}
253
+ end
254
+
255
+ it 'creates the client successfully' do
256
+ client.should be_a(Mongo::Client)
257
+ end
258
+
259
+ it 'fails all operations' do
260
+ lambda do
261
+ client.command(ping: true)
262
+ end.should raise_error(Mongo::Error::BadLoadBalancerTarget)
263
+ end
264
+ end
265
+ end
266
+
267
+ context 'when in load-balanced mode' do
268
+ require_topology :load_balanced
269
+
270
+ let(:client) do
271
+ ClientRegistry.instance.new_local_client(
272
+ [SpecConfig.instance.addresses.first],
273
+ SpecConfig.instance.test_options.merge(options),
274
+ )
275
+ end
276
+
277
+ context 'when load-balanced topology is requested via the URI option' do
278
+ let(:options) do
279
+ {connect: nil, load_balanced: true}
280
+ end
281
+
282
+ it 'creates the client successfully' do
283
+ client.should be_a(Mongo::Client)
284
+ end
285
+
286
+ it 'fails all operations' do
287
+ lambda do
288
+ client.command(ping: true)
289
+ end.should raise_error(Mongo::Error::MissingServiceId)
290
+ end
291
+ end
292
+ end
239
293
  end
@@ -11,7 +11,7 @@ describe 'Bulk writes with auto-encryption enabled' do
11
11
  include_context 'define shared FLE helpers'
12
12
  include_context 'with local kms_providers'
13
13
 
14
- let(:subscriber) { EventSubscriber.new }
14
+ let(:subscriber) { Mrss::EventSubscriber.new }
15
15
 
16
16
  let(:client) do
17
17
  new_local_client(
@@ -15,7 +15,7 @@ describe 'Auto Encryption' do
15
15
  include_context 'define shared FLE helpers'
16
16
  include_context 'with local kms_providers'
17
17
 
18
- let(:subscriber) { EventSubscriber.new }
18
+ let(:subscriber) { Mrss::EventSubscriber.new }
19
19
  let(:db_name) { 'auto_encryption' }
20
20
 
21
21
  let(:encryption_client) do
@@ -11,7 +11,7 @@ describe 'Client-Side Encryption' do
11
11
 
12
12
  include_context 'define shared FLE helpers'
13
13
 
14
- let(:subscriber) { EventSubscriber.new }
14
+ let(:subscriber) { Mrss::EventSubscriber.new }
15
15
 
16
16
  let(:client) do
17
17
  authorized_client.use('db')
@@ -11,7 +11,7 @@ describe 'Client-Side Encryption' do
11
11
 
12
12
  include_context 'define shared FLE helpers'
13
13
 
14
- let(:subscriber) { EventSubscriber.new }
14
+ let(:subscriber) { Mrss::EventSubscriber.new }
15
15
 
16
16
  let(:client) do
17
17
  new_local_client(
@@ -21,6 +21,8 @@ describe 'Client' do
21
21
  end
22
22
 
23
23
  context 'after all servers are marked unknown' do
24
+ require_topology :single, :replica_set, :sharded
25
+
24
26
  before do
25
27
  client.cluster.servers.each do |server|
26
28
  server.unknown!
@@ -5,7 +5,7 @@ require 'spec_helper'
5
5
 
6
6
  describe 'Command monitoring' do
7
7
 
8
- let(:subscriber) { EventSubscriber.new }
8
+ let(:subscriber) { Mrss::EventSubscriber.new }
9
9
 
10
10
  let(:client) do
11
11
  authorized_client.with(app_name: 'command monitoring spec').tap do |client|
@@ -5,7 +5,7 @@ require 'spec_helper'
5
5
 
6
6
  describe 'Command' do
7
7
 
8
- let(:subscriber) { EventSubscriber.new }
8
+ let(:subscriber) { Mrss::EventSubscriber.new }
9
9
 
10
10
  describe 'payload' do
11
11
  let(:server) { authorized_client.cluster.next_primary }
@@ -50,7 +50,7 @@ describe 'Connections' do
50
50
 
51
51
  context 'with sdam event subscription' do
52
52
 
53
- let(:subscriber) { EventSubscriber.new }
53
+ let(:subscriber) { Mrss::EventSubscriber.new }
54
54
  let(:client) do
55
55
  ClientRegistry.instance.global_client('authorized').with(app_name: 'connection_integration').tap do |client|
56
56
  client.subscribe(Mongo::Monitoring::SERVER_OPENING, subscriber)
@@ -246,43 +246,60 @@ describe 'Connections' do
246
246
 
247
247
  let(:client) { ClientRegistry.instance.global_client('authorized').with(app_name: 'wire_protocol_update') }
248
248
 
249
- it 'updates on hello response from non-monitoring connections' do
250
- # connect server
251
- client['test'].insert_one(test: 1)
249
+ context 'non-lb' do
250
+ require_topology :single, :replica_set, :sharded
252
251
 
253
- # kill background threads so that they are not interfering with
254
- # our mocked hello response
255
- client.cluster.servers.each do |server|
256
- server.monitor.stop!
252
+ it 'updates on handshake response from non-monitoring connections' do
253
+ # connect server
254
+ client['test'].insert_one(test: 1)
255
+
256
+ # kill background threads so that they are not interfering with
257
+ # our mocked hello response
258
+ client.cluster.servers.each do |server|
259
+ server.monitor.stop!
260
+ end
261
+
262
+ server = client.cluster.servers.first
263
+ expect(server.features.server_wire_versions.max >= 4).to be true
264
+ max_version = server.features.server_wire_versions.max
265
+
266
+ # Depending on server version, handshake here may return a
267
+ # description that compares equal to the one we got from a
268
+ # monitoring connection (pre-4.2) or not (4.2+).
269
+ # Since we do run SDAM flow on handshake responses on
270
+ # non-monitoring connections, force descriptions to be different
271
+ # by setting the existing description here to unknown.
272
+ server.monitor.instance_variable_set('@description',
273
+ Mongo::Server::Description.new(server.address))
274
+
275
+ RSpec::Mocks.with_temporary_scope do
276
+ # now pretend a handshake returned a different range
277
+ features = Mongo::Server::Description::Features.new(0..3)
278
+ # One Features instantiation is for SDAM event publication, this
279
+ # one always happens. The second one happens on servers
280
+ # where we do not negotiate auth mechanism.
281
+ expect(Mongo::Server::Description::Features).to receive(:new).at_least(:once).and_return(features)
282
+
283
+ connection = Mongo::Server::Connection.new(server, server.options)
284
+ expect(connection.connect!).to be true
285
+
286
+ # hello response should update server description via sdam flow,
287
+ # which includes wire version range
288
+ expect(server.features.server_wire_versions.max).to eq(3)
289
+ end
257
290
  end
291
+ end
292
+
293
+ context 'lb' do
294
+ require_topology :load_balanced
295
+
296
+ it 'does not update on handshake response from non-monitoring connections since there are not any' do
297
+ # connect server
298
+ client['test'].insert_one(test: 1)
258
299
 
259
- server = client.cluster.servers.first
260
- expect(server.features.server_wire_versions.max >= 4).to be true
261
- max_version = server.features.server_wire_versions.max
262
-
263
- # Depending on server version, hello here may return a
264
- # description that compares equal to the one we got from a
265
- # monitoring connection (pre-4.2) or not (4.2+).
266
- # Since we do run SDAM flow on hello responses on
267
- # non-monitoring connections, force descriptions to be different
268
- # by setting the existing description here to unknown.
269
- server.monitor.instance_variable_set('@description',
270
- Mongo::Server::Description.new(server.address))
271
-
272
- RSpec::Mocks.with_temporary_scope do
273
- # now pretend a hello returned a different range
274
- features = Mongo::Server::Description::Features.new(0..3)
275
- # One Features instantiation is for SDAM event publication, this
276
- # one always happens. The second one happens on servers
277
- # where we do not negotiate auth mechanism.
278
- expect(Mongo::Server::Description::Features).to receive(:new).at_least(:once).and_return(features)
279
-
280
- connection = Mongo::Server::Connection.new(server, server.options)
281
- expect(connection.connect!).to be true
282
-
283
- # hello response should update server description via sdam flow,
284
- # which includes wire version range
285
- expect(server.features.server_wire_versions.max).to eq(3)
300
+ server = client.cluster.servers.first
301
+ server.load_balancer?.should be true
302
+ server.features.server_wire_versions.max.should be 0
286
303
  end
287
304
  end
288
305
  end
@@ -4,7 +4,8 @@
4
4
  require 'spec_helper'
5
5
 
6
6
  describe 'CRUD operations' do
7
- let(:collection) { authorized_client['crud_integration'] }
7
+ let(:client) { authorized_client }
8
+ let(:collection) { client['crud_integration'] }
8
9
 
9
10
  before do
10
11
  collection.delete_many
@@ -64,6 +65,178 @@ describe 'CRUD operations' do
64
65
  end
65
66
  end
66
67
  end
68
+
69
+ context 'with read concern' do
70
+ # Read concern requires 3.2+ server.
71
+ min_server_fcv '3.2'
72
+
73
+ context 'with read concern specified on operation level' do
74
+
75
+ it 'passes the read concern' do
76
+ event = Utils.get_command_event(client, 'find') do |client|
77
+ client['foo'].find({}, read_concern: {level: :local}).to_a
78
+ end
79
+ event.command.fetch('readConcern').should == {'level' => 'local'}
80
+ end
81
+ end
82
+
83
+ context 'with read concern specified on collection level' do
84
+
85
+ it 'passes the read concern' do
86
+ event = Utils.get_command_event(client, 'find') do |client|
87
+ client['foo', read_concern: {level: :local}].find.to_a
88
+ end
89
+ event.command.fetch('readConcern').should == {'level' => 'local'}
90
+ end
91
+ end
92
+
93
+ context 'with read concern specified on client level' do
94
+
95
+ let(:client) { authorized_client.with(read_concern: {level: :local}) }
96
+
97
+ it 'passes the read concern' do
98
+ event = Utils.get_command_event(client, 'find') do |client|
99
+ client['foo'].find.to_a
100
+ end
101
+ event.command.fetch('readConcern').should == {'level' => 'local'}
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'with oplog_replay option' do
107
+ let(:collection_name) { 'crud_integration_oplog_replay' }
108
+
109
+ let(:oplog_query) do
110
+ {ts: {'$gt' => 1}}
111
+ end
112
+
113
+ context 'passed to operation' do
114
+ it 'passes the option' do
115
+ event = Utils.get_command_event(client, 'find') do |client|
116
+ client[collection_name].find(oplog_query, oplog_replay: true).to_a
117
+ end
118
+ event.command.fetch('oplogReplay').should be true
119
+ end
120
+
121
+ it 'warns' do
122
+ client.should receive(:log_warn).with('The :oplog_replay option is deprecated and ignored by MongoDB 4.4 and later')
123
+ client[collection_name].find(oplog_query, oplog_replay: true).to_a
124
+ end
125
+ end
126
+
127
+ context 'set on collection' do
128
+ it 'passes the option' do
129
+ event = Utils.get_command_event(client, 'find') do |client|
130
+ client[collection_name, oplog_replay: true].find(oplog_query).to_a
131
+ end
132
+ event.command.fetch('oplogReplay').should be true
133
+ end
134
+
135
+ it 'warns' do
136
+ client.should receive(:log_warn).with('The :oplog_replay option is deprecated and ignored by MongoDB 4.4 and later')
137
+ client[collection_name, oplog_replay: true].find(oplog_query).to_a
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'explain' do
144
+ context 'with explicit session' do
145
+ min_server_fcv '3.6'
146
+
147
+ it 'passes the session' do
148
+ client.start_session do |session|
149
+ event = Utils.get_command_event(client, 'explain') do |client|
150
+ client['foo'].find({}, session: session).explain.should be_explain_output
151
+ end
152
+ event.command.fetch('lsid').should == session.session_id
153
+ end
154
+ end
155
+ end
156
+
157
+ context 'with read preference specified on operation level' do
158
+ require_topology :sharded
159
+
160
+ # RUBY-2706
161
+ min_server_fcv '3.6'
162
+
163
+ it 'passes the read preference' do
164
+ event = Utils.get_command_event(client, 'explain') do |client|
165
+ client['foo'].find({}, read: {mode: :secondary_preferred}).explain.should be_explain_output
166
+ end
167
+ event.command.fetch('$readPreference').should == {'mode' => 'secondaryPreferred'}
168
+ end
169
+ end
170
+
171
+ context 'with read preference specified on collection level' do
172
+ require_topology :sharded
173
+
174
+ # RUBY-2706
175
+ min_server_fcv '3.6'
176
+
177
+ it 'passes the read preference' do
178
+ event = Utils.get_command_event(client, 'explain') do |client|
179
+ client['foo', read: {mode: :secondary_preferred}].find.explain.should be_explain_output
180
+ end
181
+ event.command.fetch('$readPreference').should == {'mode' => 'secondaryPreferred'}
182
+ end
183
+ end
184
+
185
+ context 'with read preference specified on client level' do
186
+ require_topology :sharded
187
+
188
+ # RUBY-2706
189
+ min_server_fcv '3.6'
190
+
191
+ let(:client) { authorized_client.with(read: {mode: :secondary_preferred}) }
192
+
193
+ it 'passes the read preference' do
194
+ event = Utils.get_command_event(client, 'explain') do |client|
195
+ client['foo'].find.explain.should be_explain_output
196
+ end
197
+ event.command.fetch('$readPreference').should == {'mode' => 'secondaryPreferred'}
198
+ end
199
+ end
200
+
201
+ context 'with read concern' do
202
+ # Read concern requires 3.2+ server.
203
+ min_server_fcv '3.2'
204
+
205
+ context 'with read concern specifed on operation level' do
206
+
207
+ # Read concern is not allowed in explain command, driver drops it.
208
+ it 'drops the read concern' do
209
+ event = Utils.get_command_event(client, 'explain') do |client|
210
+ client['foo'].find({}, read_concern: {level: :local}).explain.should have_key('queryPlanner')
211
+ end
212
+ event.command.should_not have_key('readConcern')
213
+ end
214
+ end
215
+
216
+ context 'with read concern specifed on collection level' do
217
+
218
+ # Read concern is not allowed in explain command, driver drops it.
219
+ it 'drops the read concern' do
220
+ event = Utils.get_command_event(client, 'explain') do |client|
221
+ client['foo', read_concern: {level: :local}].find.explain.should have_key('queryPlanner')
222
+ end
223
+ event.command.should_not have_key('readConcern')
224
+ end
225
+ end
226
+
227
+ context 'with read concern specifed on client level' do
228
+
229
+ let(:client) { authorized_client.with(read_concern: {level: :local}) }
230
+
231
+ # Read concern is not allowed in explain command, driver drops it.
232
+ it 'drops the read concern' do
233
+ event = Utils.get_command_event(client, 'explain') do |client|
234
+ client['foo'].find.explain.should have_key('queryPlanner')
235
+ end
236
+ event.command.should_not have_key('readConcern')
237
+ end
238
+ end
239
+ end
67
240
  end
68
241
 
69
242
  describe 'insert' do