mongo 2.13.0.beta1 → 2.14.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 (339) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +50 -9
  5. data/lib/mongo.rb +13 -2
  6. data/lib/mongo/address.rb +1 -1
  7. data/lib/mongo/address/ipv4.rb +1 -1
  8. data/lib/mongo/address/ipv6.rb +1 -1
  9. data/lib/mongo/auth/aws/request.rb +31 -5
  10. data/lib/mongo/bulk_write.rb +18 -0
  11. data/lib/mongo/caching_cursor.rb +74 -0
  12. data/lib/mongo/client.rb +238 -31
  13. data/lib/mongo/cluster.rb +56 -20
  14. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  15. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  16. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  17. data/lib/mongo/cluster/topology/single.rb +2 -2
  18. data/lib/mongo/collection.rb +66 -24
  19. data/lib/mongo/collection/view.rb +24 -20
  20. data/lib/mongo/collection/view/aggregation.rb +25 -4
  21. data/lib/mongo/collection/view/builder/find_command.rb +38 -18
  22. data/lib/mongo/collection/view/explainable.rb +27 -8
  23. data/lib/mongo/collection/view/iterable.rb +72 -12
  24. data/lib/mongo/collection/view/readable.rb +19 -3
  25. data/lib/mongo/collection/view/writable.rb +55 -5
  26. data/lib/mongo/crypt/encryption_io.rb +6 -6
  27. data/lib/mongo/cursor.rb +16 -3
  28. data/lib/mongo/database.rb +37 -4
  29. data/lib/mongo/database/view.rb +18 -3
  30. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  31. data/lib/mongo/error.rb +5 -0
  32. data/lib/mongo/error/invalid_read_concern.rb +28 -0
  33. data/lib/mongo/error/invalid_server_auth_host.rb +22 -0
  34. data/lib/mongo/error/invalid_session.rb +2 -1
  35. data/lib/mongo/error/operation_failure.rb +11 -5
  36. data/lib/mongo/error/server_certificate_revoked.rb +22 -0
  37. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  38. data/lib/mongo/error/unsupported_option.rb +14 -12
  39. data/lib/mongo/event/base.rb +6 -0
  40. data/lib/mongo/grid/file.rb +5 -0
  41. data/lib/mongo/grid/file/chunk.rb +2 -0
  42. data/lib/mongo/grid/fs_bucket.rb +15 -13
  43. data/lib/mongo/grid/stream/write.rb +9 -3
  44. data/lib/mongo/index/view.rb +3 -0
  45. data/lib/mongo/lint.rb +2 -1
  46. data/lib/mongo/logger.rb +3 -3
  47. data/lib/mongo/monitoring.rb +38 -0
  48. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  49. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  50. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  51. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  52. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  53. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  54. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  55. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  56. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  57. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  58. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  59. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  60. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  61. data/lib/mongo/monitoring/publishable.rb +6 -3
  62. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  63. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  64. data/lib/mongo/operation.rb +2 -0
  65. data/lib/mongo/operation/aggregate/result.rb +9 -8
  66. data/lib/mongo/operation/collections_info/command.rb +5 -0
  67. data/lib/mongo/operation/collections_info/result.rb +18 -1
  68. data/lib/mongo/operation/delete/bulk_result.rb +2 -0
  69. data/lib/mongo/operation/delete/result.rb +3 -0
  70. data/lib/mongo/operation/explain/command.rb +4 -0
  71. data/lib/mongo/operation/explain/legacy.rb +4 -0
  72. data/lib/mongo/operation/explain/op_msg.rb +6 -0
  73. data/lib/mongo/operation/explain/result.rb +3 -0
  74. data/lib/mongo/operation/find/legacy/result.rb +2 -0
  75. data/lib/mongo/operation/find/result.rb +13 -0
  76. data/lib/mongo/operation/get_more/result.rb +3 -0
  77. data/lib/mongo/operation/indexes/result.rb +5 -0
  78. data/lib/mongo/operation/insert/bulk_result.rb +5 -0
  79. data/lib/mongo/operation/insert/result.rb +5 -0
  80. data/lib/mongo/operation/list_collections/result.rb +5 -0
  81. data/lib/mongo/operation/map_reduce/result.rb +10 -0
  82. data/lib/mongo/operation/parallel_scan/result.rb +4 -0
  83. data/lib/mongo/operation/result.rb +35 -6
  84. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
  85. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
  86. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
  87. data/lib/mongo/operation/shared/executable.rb +1 -0
  88. data/lib/mongo/operation/shared/idable.rb +2 -1
  89. data/lib/mongo/operation/shared/limited.rb +1 -0
  90. data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
  91. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
  92. data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
  93. data/lib/mongo/operation/shared/specifiable.rb +1 -0
  94. data/lib/mongo/operation/shared/write.rb +1 -0
  95. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
  96. data/lib/mongo/operation/update/legacy/result.rb +7 -0
  97. data/lib/mongo/operation/update/result.rb +8 -0
  98. data/lib/mongo/operation/users_info/result.rb +3 -0
  99. data/lib/mongo/protocol/message.rb +47 -10
  100. data/lib/mongo/protocol/msg.rb +34 -1
  101. data/lib/mongo/protocol/query.rb +36 -0
  102. data/lib/mongo/protocol/serializers.rb +5 -2
  103. data/lib/mongo/query_cache.rb +242 -0
  104. data/lib/mongo/retryable.rb +8 -1
  105. data/lib/mongo/server.rb +15 -4
  106. data/lib/mongo/server/app_metadata.rb +27 -3
  107. data/lib/mongo/server/connection.rb +4 -4
  108. data/lib/mongo/server/connection_base.rb +38 -12
  109. data/lib/mongo/server/connection_common.rb +2 -2
  110. data/lib/mongo/server/connection_pool.rb +3 -0
  111. data/lib/mongo/server/description.rb +13 -1
  112. data/lib/mongo/server/monitor.rb +76 -44
  113. data/lib/mongo/server/monitor/connection.rb +57 -9
  114. data/lib/mongo/server/pending_connection.rb +14 -4
  115. data/lib/mongo/server/push_monitor.rb +173 -0
  116. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  117. data/lib/mongo/server_selector.rb +0 -1
  118. data/lib/mongo/server_selector/base.rb +583 -1
  119. data/lib/mongo/server_selector/nearest.rb +1 -6
  120. data/lib/mongo/server_selector/primary.rb +1 -6
  121. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  122. data/lib/mongo/server_selector/secondary.rb +1 -6
  123. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  124. data/lib/mongo/session.rb +7 -1
  125. data/lib/mongo/socket.rb +26 -12
  126. data/lib/mongo/socket/ocsp_cache.rb +97 -0
  127. data/lib/mongo/socket/ocsp_verifier.rb +368 -0
  128. data/lib/mongo/socket/ssl.rb +46 -25
  129. data/lib/mongo/socket/tcp.rb +1 -1
  130. data/lib/mongo/srv/monitor.rb +7 -13
  131. data/lib/mongo/srv/resolver.rb +14 -10
  132. data/lib/mongo/timeout.rb +2 -0
  133. data/lib/mongo/topology_version.rb +9 -0
  134. data/lib/mongo/uri.rb +21 -390
  135. data/lib/mongo/uri/options_mapper.rb +582 -0
  136. data/lib/mongo/uri/srv_protocol.rb +3 -2
  137. data/lib/mongo/utils.rb +73 -0
  138. data/lib/mongo/version.rb +1 -1
  139. data/spec/NOTES.aws-auth.md +12 -7
  140. data/spec/README.aws-auth.md +2 -2
  141. data/spec/README.md +63 -1
  142. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  143. data/spec/integration/bson_symbol_spec.rb +4 -2
  144. data/spec/integration/bulk_write_spec.rb +67 -0
  145. data/spec/integration/change_stream_examples_spec.rb +6 -2
  146. data/spec/integration/change_stream_spec.rb +1 -1
  147. data/spec/integration/check_clean_slate_spec.rb +16 -0
  148. data/spec/integration/client_authentication_options_spec.rb +92 -28
  149. data/spec/integration/client_construction_spec.rb +1 -0
  150. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +9 -5
  151. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  152. data/spec/integration/connection_pool_populator_spec.rb +4 -2
  153. data/spec/integration/connection_spec.rb +7 -4
  154. data/spec/integration/crud_spec.rb +4 -4
  155. data/spec/integration/cursor_reaping_spec.rb +54 -18
  156. data/spec/integration/docs_examples_spec.rb +6 -0
  157. data/spec/integration/fork_reconnect_spec.rb +56 -1
  158. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  159. data/spec/integration/heartbeat_events_spec.rb +4 -23
  160. data/spec/integration/ocsp_connectivity_spec.rb +26 -0
  161. data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
  162. data/spec/integration/ocsp_verifier_spec.rb +334 -0
  163. data/spec/integration/query_cache_spec.rb +1045 -0
  164. data/spec/integration/query_cache_transactions_spec.rb +190 -0
  165. data/spec/integration/read_concern_spec.rb +1 -1
  166. data/spec/integration/retryable_errors_spec.rb +1 -1
  167. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
  168. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +4 -2
  169. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  170. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  171. data/spec/integration/sdam_error_handling_spec.rb +122 -15
  172. data/spec/integration/sdam_events_spec.rb +80 -6
  173. data/spec/integration/sdam_prose_spec.rb +64 -0
  174. data/spec/integration/server_monitor_spec.rb +25 -1
  175. data/spec/integration/server_selection_spec.rb +36 -0
  176. data/spec/integration/size_limit_spec.rb +23 -5
  177. data/spec/integration/srv_monitoring_spec.rb +38 -3
  178. data/spec/integration/srv_spec.rb +56 -0
  179. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  180. data/spec/integration/transactions_examples_spec.rb +17 -7
  181. data/spec/integration/zlib_compression_spec.rb +25 -0
  182. data/spec/lite_spec_helper.rb +20 -9
  183. data/spec/mongo/address_spec.rb +1 -1
  184. data/spec/mongo/auth/aws/request_region_spec.rb +42 -0
  185. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  186. data/spec/mongo/auth/scram_spec.rb +1 -1
  187. data/spec/mongo/auth/user_spec.rb +1 -1
  188. data/spec/mongo/bulk_write_spec.rb +2 -2
  189. data/spec/mongo/caching_cursor_spec.rb +70 -0
  190. data/spec/mongo/client_construction_spec.rb +386 -3
  191. data/spec/mongo/client_encryption_spec.rb +16 -10
  192. data/spec/mongo/client_spec.rb +85 -3
  193. data/spec/mongo/cluster/topology/replica_set_spec.rb +53 -10
  194. data/spec/mongo/cluster/topology/sharded_spec.rb +1 -1
  195. data/spec/mongo/cluster/topology/single_spec.rb +19 -8
  196. data/spec/mongo/cluster/topology/unknown_spec.rb +1 -1
  197. data/spec/mongo/cluster/topology_spec.rb +1 -1
  198. data/spec/mongo/cluster_spec.rb +37 -35
  199. data/spec/mongo/collection/view/change_stream_resume_spec.rb +7 -7
  200. data/spec/mongo/collection/view/explainable_spec.rb +87 -4
  201. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
  202. data/spec/mongo/collection/view/readable_spec.rb +36 -0
  203. data/spec/mongo/collection_spec.rb +572 -0
  204. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  205. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  206. data/spec/mongo/crypt/binary_spec.rb +1 -6
  207. data/spec/mongo/crypt/binding/binary_spec.rb +1 -6
  208. data/spec/mongo/crypt/binding/context_spec.rb +2 -7
  209. data/spec/mongo/crypt/binding/helpers_spec.rb +1 -6
  210. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +2 -7
  211. data/spec/mongo/crypt/binding/status_spec.rb +1 -6
  212. data/spec/mongo/crypt/binding/version_spec.rb +1 -6
  213. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  214. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  215. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
  216. data/spec/mongo/crypt/status_spec.rb +1 -6
  217. data/spec/mongo/database_spec.rb +353 -8
  218. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  219. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  220. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  221. data/spec/mongo/index/view_spec.rb +148 -2
  222. data/spec/mongo/logger_spec.rb +13 -11
  223. data/spec/mongo/monitoring/event/server_closed_spec.rb +1 -1
  224. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  225. data/spec/mongo/monitoring/event/server_opening_spec.rb +1 -1
  226. data/spec/mongo/monitoring/event/topology_changed_spec.rb +1 -1
  227. data/spec/mongo/monitoring/event/topology_closed_spec.rb +1 -1
  228. data/spec/mongo/monitoring/event/topology_opening_spec.rb +1 -1
  229. data/spec/mongo/operation/delete/op_msg_spec.rb +3 -3
  230. data/spec/mongo/operation/insert/command_spec.rb +2 -2
  231. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -3
  232. data/spec/mongo/operation/read_preference_op_msg_spec.rb +1 -1
  233. data/spec/mongo/operation/update/command_spec.rb +2 -2
  234. data/spec/mongo/operation/update/op_msg_spec.rb +3 -3
  235. data/spec/mongo/protocol/msg_spec.rb +10 -0
  236. data/spec/mongo/query_cache_spec.rb +280 -0
  237. data/spec/mongo/semaphore_spec.rb +51 -0
  238. data/spec/mongo/server/app_metadata_shared.rb +82 -2
  239. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  240. data/spec/mongo/server/connection_pool_spec.rb +7 -3
  241. data/spec/mongo/server/connection_spec.rb +15 -8
  242. data/spec/mongo/server/description_spec.rb +18 -0
  243. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  244. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  245. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  246. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  247. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  248. data/spec/mongo/server_selector_spec.rb +6 -6
  249. data/spec/mongo/session_spec.rb +35 -0
  250. data/spec/mongo/socket/ssl_spec.rb +4 -4
  251. data/spec/mongo/socket_spec.rb +1 -1
  252. data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
  253. data/spec/mongo/uri_option_parsing_spec.rb +11 -11
  254. data/spec/mongo/uri_spec.rb +68 -41
  255. data/spec/mongo/utils_spec.rb +39 -0
  256. data/spec/runners/auth.rb +3 -0
  257. data/spec/runners/change_streams/test.rb +3 -3
  258. data/spec/runners/cmap.rb +1 -1
  259. data/spec/runners/command_monitoring.rb +3 -34
  260. data/spec/runners/connection_string.rb +35 -124
  261. data/spec/runners/crud/context.rb +9 -5
  262. data/spec/runners/crud/operation.rb +59 -27
  263. data/spec/runners/crud/spec.rb +0 -8
  264. data/spec/runners/crud/test.rb +1 -1
  265. data/spec/runners/crud/test_base.rb +0 -19
  266. data/spec/runners/sdam.rb +2 -2
  267. data/spec/runners/server_selection.rb +242 -28
  268. data/spec/runners/transactions.rb +12 -12
  269. data/spec/runners/transactions/operation.rb +151 -25
  270. data/spec/runners/transactions/test.rb +62 -18
  271. data/spec/shared/LICENSE +20 -0
  272. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  273. data/spec/shared/lib/mrss/constraints.rb +303 -0
  274. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  275. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  276. data/spec/spec_helper.rb +3 -1
  277. data/spec/spec_tests/cmap_spec.rb +7 -3
  278. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  279. data/spec/spec_tests/crud_spec.rb +1 -1
  280. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -9
  281. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  282. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  283. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  284. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  285. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  288. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  289. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  290. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  291. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  292. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  293. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  294. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  295. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  296. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  297. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  298. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  299. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
  300. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
  301. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  302. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  303. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  304. data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
  305. data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
  306. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  307. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
  308. data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
  309. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
  310. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  311. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  312. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  313. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  314. data/spec/spec_tests/server_selection_spec.rb +4 -116
  315. data/spec/spec_tests/uri_options_spec.rb +31 -33
  316. data/spec/stress/cleanup_spec.rb +17 -2
  317. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  318. data/spec/stress/fork_reconnect_stress_spec.rb +1 -1
  319. data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
  320. data/spec/support/certificates/atlas-ocsp.crt +41 -0
  321. data/spec/support/client_registry.rb +1 -0
  322. data/spec/support/client_registry_macros.rb +11 -2
  323. data/spec/support/cluster_config.rb +4 -0
  324. data/spec/support/common_shortcuts.rb +45 -0
  325. data/spec/support/constraints.rb +6 -253
  326. data/spec/support/event_subscriber.rb +123 -33
  327. data/spec/support/keyword_struct.rb +26 -0
  328. data/spec/support/matchers.rb +16 -0
  329. data/spec/support/ocsp +1 -0
  330. data/spec/support/session_registry.rb +52 -0
  331. data/spec/support/shared/server_selector.rb +13 -1
  332. data/spec/support/spec_config.rb +60 -13
  333. data/spec/support/spec_setup.rb +1 -1
  334. data/spec/support/utils.rb +84 -1
  335. metadata +1027 -937
  336. metadata.gz.sig +0 -0
  337. data/lib/mongo/server_selector/selectable.rb +0 -560
  338. data/spec/runners/sdam_monitoring.rb +0 -89
  339. data/spec/support/lite_constraints.rb +0 -141
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f5e58cfb13fc60fb774becdceb53b4c79cd1461a2cbd3f2dcfd44216f083da8
4
- data.tar.gz: df770f62315fa3ef4db7a32d796c093759a38c1e6c4e6eaa183789b1700f5ed9
3
+ metadata.gz: 7bfb22d052a842e256744a88c7e3cbd3b958643cc3e0f4425bf97be8f913f167
4
+ data.tar.gz: b63f3605ad8223e99a5f6a62aabff94a8c8600095b84265b6b4deb38e7223013
5
5
  SHA512:
6
- metadata.gz: a51aa55384766e936b0bbc4ad2f99c9fb22ad03d10e04a4f65a5492c16764c92495ae17c5e1ba521c96e3fe25c5b2d787ab985939947eeffd0957a54ceef4078
7
- data.tar.gz: 6d8ca3220081914ec39479c4c9ebb4a6f070be7f4840fa98f0b6cf28f9c3a9c8082264e9b3b7b0d588cda54f97c9f687e36fd467576a396527d80b493c8a52e7
6
+ metadata.gz: 85566c0080b9bcfa67438a365114dd062425df557040e05c0db0448aedd37a0f52dae5b8612b08af196a9e35c1e5b41553a89607d780d187d4e2e28602471c76
7
+ data.tar.gz: 5172ab2d71a8d7e048fcb2d87e7219024a2028c3909f2cce48081d1b3014071df13b02426019508bda6542e4870992ca869cd3393caf3aaf6483ad4c74f1abf3
Binary file
data.tar.gz.sig CHANGED
@@ -1,5 +1 @@
1
- �⋎�L��`�*Vd��
2
- �J���5_E:���
3
- �&E�!��Z�E:���%-%sZY��_��5 �o�����I�AB�׵X��������������R��7�88_}lB�<&06�.W�����eJu�A�
4
- M��QhuF-0�)��_ b���y��i�9q
5
- Q��E:8�H��7 0'� �����º���q�<����[�_���[��k_s���� >��RՐ;�5iq.�[��~��'9�������%
1
+ ��0���H#{�F���� ��ƛ!z�����}��6l��kM��h.[��hAi�<y/&BM~|2��֘�s�s����o@�]k�d�w�xǴp+��ȿ�
data/Rakefile CHANGED
@@ -13,7 +13,31 @@ end
13
13
  default_groups = [:default, :testing]
14
14
  Bundler.require(*default_groups)
15
15
 
16
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__)))
17
+
18
+ $: << File.join(ROOT, 'spec/shared/lib')
19
+
16
20
  require 'rspec/core/rake_task'
21
+ require 'mrss/spec_organizer'
22
+
23
+ CLASSIFIERS = [
24
+ [%r,^mongo,, :unit],
25
+ [%r,^kerberos,, :unit],
26
+ [%r,^integration/sdam_error_handling,, :sdam_integration],
27
+ [%r,^integration/cursor_reaping,, :cursor_reaping],
28
+ [%r,^integration/query_cache,, :query_cache],
29
+ [%r,^integration/transactions_examples,, :tx_examples],
30
+ [%r,^(atlas|integration),, :integration],
31
+ [%r,^spec_tests/sdam_integration,, :spec_sdam_integration],
32
+ [%r,^spec_tests,, :spec],
33
+ ]
34
+
35
+ RUN_PRIORITY = %i(
36
+ tx_examples
37
+ unit
38
+ integration sdam_integration cursor_reaping query_cache
39
+ spec spec_sdam_integration
40
+ )
17
41
 
18
42
  tasks = Rake.application.instance_variable_get('@tasks')
19
43
  tasks['release:do'] = tasks.delete('release')
@@ -45,16 +69,16 @@ namespace :spec do
45
69
  client = ClientRegistry.instance.global_client('authorized')
46
70
  client.database.command(ping: 1)
47
71
  deadline = Time.now + 300
48
- while Time.now < deadline
49
- if client.cluster.send(:sessions_supported?)
72
+ loop do
73
+ begin
74
+ client.cluster.validate_session_support!
50
75
  break
76
+ rescue Mongo::Error::SessionsNotSupported
77
+ if Time.now >= deadline
78
+ raise "Sessions did not become supported in 300 seconds"
79
+ end
80
+ client.cluster.scan!
51
81
  end
52
- sleep 1
53
- client.close
54
- client.reconnect
55
- end
56
- unless client.cluster.send(:sessions_supported?)
57
- raise "Sessions did not become supported in the allowed time"
58
82
  end
59
83
  end
60
84
 
@@ -71,7 +95,24 @@ namespace :spec do
71
95
  SpecConfig.instance.print_summary
72
96
  end
73
97
 
74
- task :ci => ['spec:prepare', :spec]
98
+ def spec_organizer
99
+ Mrss::SpecOrganizer.new(
100
+ root: ROOT,
101
+ classifiers: CLASSIFIERS,
102
+ priority_order: RUN_PRIORITY,
103
+ )
104
+ end
105
+
106
+ task :ci => ['spec:prepare'] do
107
+ spec_organizer.run
108
+ end
109
+
110
+ desc 'Show test buckets'
111
+ task :buckets do
112
+ spec_organizer.ordered_buckets.each do |category, paths|
113
+ puts "#{category || 'remaining'}: #{paths&.join(' ') || '<none>'}"
114
+ end
115
+ end
75
116
  end
76
117
 
77
118
  namespace :release do
@@ -34,6 +34,7 @@ require 'bson'
34
34
  require 'mongo/id'
35
35
  require 'mongo/bson'
36
36
  require 'mongo/semaphore'
37
+ require 'mongo/distinguishing_semaphore'
37
38
  require 'mongo/options'
38
39
  require 'mongo/loggable'
39
40
  require 'mongo/cluster_time'
@@ -50,13 +51,17 @@ require 'mongo/protocol'
50
51
  require 'mongo/background_thread'
51
52
  require 'mongo/cluster'
52
53
  require 'mongo/cursor'
54
+ require 'mongo/caching_cursor'
53
55
  require 'mongo/collection'
54
56
  require 'mongo/database'
55
57
  require 'mongo/crypt'
56
58
  require 'mongo/client' # Purposely out-of-order so that database is loaded first
59
+ require 'mongo/client_encryption'
57
60
  require 'mongo/dbref'
58
61
  require 'mongo/grid'
59
62
  require 'mongo/index'
63
+ require 'mongo/lint'
64
+ require 'mongo/query_cache'
60
65
  require 'mongo/server'
61
66
  require 'mongo/server_selector'
62
67
  require 'mongo/session'
@@ -66,5 +71,11 @@ require 'mongo/timeout'
66
71
  require 'mongo/uri'
67
72
  require 'mongo/version'
68
73
  require 'mongo/write_concern'
69
- require 'mongo/lint'
70
- require 'mongo/client_encryption'
74
+ require 'mongo/utils'
75
+
76
+ module Mongo
77
+ # Clears the driver's OCSP response cache.
78
+ module_function def clear_ocsp_cache
79
+ Socket::OcspCache.clear
80
+ end
81
+ end
@@ -286,7 +286,7 @@ module Mongo
286
286
  rescue IOError, SystemCallError => e
287
287
  raise Error::SocketError, "#{e.class}: #{e} (for #{self})"
288
288
  rescue OpenSSL::SSL::SSLError => e
289
- raise Error::SocketError, "#{e.class}: #{e} (for #{self}) (#{SSL_ERROR})"
289
+ raise Error::SocketError, "#{e.class}: #{e} (for #{self})"
290
290
  end
291
291
  end
292
292
  end
@@ -81,7 +81,7 @@ module Mongo
81
81
  # @param [ Hash ] options The options.
82
82
  #
83
83
  # @option options [ Float ] :connect_timeout Connect timeout.
84
- # @option options [ true | false ] :ssl Whether to use SSL.
84
+ # @option options [ true | false ] :ssl Whether to use TLS.
85
85
  # @option options [ String ] :ssl_ca_cert
86
86
  # Same as the corresponding Client/Socket::SSL option.
87
87
  # @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
@@ -95,7 +95,7 @@ module Mongo
95
95
  # @param [ Hash ] options The options.
96
96
  #
97
97
  # @option options [ Float ] :connect_timeout Connect timeout.
98
- # @option options [ true | false ] :ssl Whether to use SSL.
98
+ # @option options [ true | false ] :ssl Whether to use TLS.
99
99
  # @option options [ String ] :ssl_ca_cert
100
100
  # Same as the corresponding Client/Socket::SSL option.
101
101
  # @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
@@ -12,7 +12,9 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- autoload :Net, 'net/http'
15
+ module Net
16
+ autoload :HTTP, 'net/http'
17
+ end
16
18
 
17
19
  module Mongo
18
20
  module Auth
@@ -59,9 +61,13 @@ module Mongo
59
61
  %i(access_key_id secret_access_key host server_nonce).each do |arg|
60
62
  value = instance_variable_get("@#{arg}")
61
63
  if value.nil? || value.empty?
62
- raise ArgumentError, "Value for #{arg} is required"
64
+ raise Error::InvalidServerAuthResponse, "Value for '#{arg}' is required"
63
65
  end
64
66
  end
67
+
68
+ if host && host.length > 255
69
+ raise Error::InvalidServerAuthHost, "Value for 'host' is too long: #{@host}"
70
+ end
65
71
  end
66
72
 
67
73
  # @return [ String ] access_key_id The access key id.
@@ -86,7 +92,7 @@ module Mongo
86
92
  # @return [ String ] formatted_time ISO8601-formatted time of the
87
93
  # request, as would be used in X-Amz-Date header.
88
94
  def formatted_time
89
- @formatted_time ||= @time.utc.strftime('%Y%m%dT%H%M%SZ')
95
+ @formatted_time ||= @time.getutc.strftime('%Y%m%dT%H%M%SZ')
90
96
  end
91
97
 
92
98
  # @return [ String ] formatted_date YYYYMMDD formatted date of the request.
@@ -96,8 +102,28 @@ module Mongo
96
102
 
97
103
  # @return [ String ] region The region of the host, derived from the host.
98
104
  def region
99
- # TODO implement region derivation when SPEC-1646 is done.
100
- 'us-east-1'
105
+ # Common case
106
+ if host == 'sts.amazonaws.com'
107
+ return 'us-east-1'
108
+ end
109
+
110
+ if host.start_with?('.')
111
+ raise Error::InvalidServerAuthHost, "Host begins with a period: #{host}"
112
+ end
113
+ if host.end_with?('.')
114
+ raise Error::InvalidServerAuthHost, "Host ends with a period: #{host}"
115
+ end
116
+
117
+ parts = host.split('.')
118
+ if parts.any? { |part| part.empty? }
119
+ raise Error::InvalidServerAuthHost, "Host has an empty component: #{host}"
120
+ end
121
+
122
+ if parts.length == 1
123
+ 'us-east-1'
124
+ else
125
+ parts[1]
126
+ end
101
127
  end
102
128
 
103
129
  # Returns the scope of the request, per the AWS signature V4 specification.
@@ -170,6 +170,7 @@ module Mongo
170
170
  :ordered => ordered?,
171
171
  :operation_id => operation_id,
172
172
  :bypass_document_validation => !!options[:bypass_document_validation],
173
+ :max_time_ms => options[:max_time_ms],
173
174
  :options => options,
174
175
  :id_generator => client.options[:id_generator],
175
176
  :session => session
@@ -194,6 +195,13 @@ module Mongo
194
195
  end
195
196
  end
196
197
  end
198
+ # With OP_MSG (3.6+ servers), the size of each section in the message
199
+ # is independently capped at 16m and each bulk operation becomes
200
+ # its own section. The size of the entire bulk write is limited to 48m.
201
+ # With OP_QUERY (pre-3.6 servers), the entire bulk write is sent as a
202
+ # single document and is thus subject to the 16m document size limit.
203
+ # This means the splits differ between pre-3.6 and 3.6+ servers, with
204
+ # 3.6+ servers being able to split less.
197
205
  rescue Error::MaxBSONSize, Error::MaxMessageSize => e
198
206
  raise e if values.size <= 1
199
207
  unpin_maybe(session) do
@@ -213,27 +221,37 @@ module Mongo
213
221
  end
214
222
 
215
223
  def delete_one(documents, connection, operation_id, session, txn_num)
224
+ QueryCache.clear_namespace(collection.namespace)
225
+
216
226
  spec = base_spec(operation_id, session).merge(:deletes => documents, :txn_num => txn_num)
217
227
  Operation::Delete.new(spec).bulk_execute(connection, client: client)
218
228
  end
219
229
 
220
230
  def delete_many(documents, connection, operation_id, session, txn_num)
231
+ QueryCache.clear_namespace(collection.namespace)
232
+
221
233
  spec = base_spec(operation_id, session).merge(:deletes => documents)
222
234
  Operation::Delete.new(spec).bulk_execute(connection, client: client)
223
235
  end
224
236
 
225
237
  def insert_one(documents, connection, operation_id, session, txn_num)
238
+ QueryCache.clear_namespace(collection.namespace)
239
+
226
240
  spec = base_spec(operation_id, session).merge(:documents => documents, :txn_num => txn_num)
227
241
  Operation::Insert.new(spec).bulk_execute(connection, client: client)
228
242
  end
229
243
 
230
244
  def update_one(documents, connection, operation_id, session, txn_num)
245
+ QueryCache.clear_namespace(collection.namespace)
246
+
231
247
  spec = base_spec(operation_id, session).merge(:updates => documents, :txn_num => txn_num)
232
248
  Operation::Update.new(spec).bulk_execute(connection, client: client)
233
249
  end
234
250
  alias :replace_one :update_one
235
251
 
236
252
  def update_many(documents, connection, operation_id, session, txn_num)
253
+ QueryCache.clear_namespace(collection.namespace)
254
+
237
255
  spec = base_spec(operation_id, session).merge(:updates => documents)
238
256
  Operation::Update.new(spec).bulk_execute(connection, client: client)
239
257
  end
@@ -0,0 +1,74 @@
1
+ # Copyright (C) 2020 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+
17
+ # A Cursor that attempts to load documents from memory first before hitting
18
+ # the database if the same query has already been executed.
19
+ #
20
+ # @api semiprivate
21
+ class CachingCursor < Cursor
22
+
23
+ # @return [ Array <BSON::Document> ] The cursor's cached documents.
24
+ # @api private
25
+ attr_reader :cached_docs
26
+
27
+ # We iterate over the cached documents if they exist already in the
28
+ # cursor otherwise proceed as normal.
29
+ #
30
+ # @example Iterate over the documents.
31
+ # cursor.each do |doc|
32
+ # # ...
33
+ # end
34
+ def each
35
+ if @cached_docs
36
+ @cached_docs.each do |doc|
37
+ yield doc
38
+ end
39
+
40
+ unless closed?
41
+ # StopIteration raised by try_next ends this loop.
42
+ loop do
43
+ document = try_next
44
+ yield document if document
45
+ end
46
+ end
47
+ else
48
+ super
49
+ end
50
+ end
51
+
52
+ # Get a human-readable string representation of +Cursor+.
53
+ #
54
+ # @example Inspect the cursor.
55
+ # cursor.inspect
56
+ #
57
+ # @return [ String ] A string representation of a +Cursor+ instance.
58
+ def inspect
59
+ "#<Mongo::CachingCursor:0x#{object_id} @view=#{@view.inspect}>"
60
+ end
61
+
62
+ # Acquires the next document for cursor iteration and then
63
+ # inserts that document in the @cached_docs array.
64
+ #
65
+ # @api private
66
+ def try_next
67
+ @cached_docs ||= []
68
+ document = super
69
+ @cached_docs << document if document
70
+
71
+ document
72
+ end
73
+ end
74
+ end
@@ -55,6 +55,7 @@ module Mongo
55
55
  :auth_mech_properties,
56
56
  :auth_source,
57
57
  :auto_encryption_options,
58
+ :bg_error_backtrace,
58
59
  :cleanup,
59
60
  :compressors,
60
61
  :direct_connection,
@@ -100,9 +101,11 @@ module Mongo
100
101
  :ssl_verify,
101
102
  :ssl_verify_certificate,
102
103
  :ssl_verify_hostname,
104
+ :ssl_verify_ocsp_endpoint,
103
105
  :truncate_logs,
104
106
  :user,
105
107
  :wait_queue_timeout,
108
+ :wrapping_libraries,
106
109
  :write,
107
110
  :write_concern,
108
111
  :zlib_compression_level,
@@ -213,6 +216,10 @@ module Mongo
213
216
  # use. One of :mongodb_cr, :mongodb_x509, :plain, :scram, :scram256
214
217
  # @option options [ Hash ] :auth_mech_properties
215
218
  # @option options [ String ] :auth_source The source to authenticate from.
219
+ # @option options [ true | false | nil | Integer ] :bg_error_backtrace
220
+ # Experimental. Set to true to log complete backtraces for errors in
221
+ # background threads. Set to false or nil to not log backtraces. Provide
222
+ # a positive integer to log up to that many backtrace lines.
216
223
  # @option options [ Array<String> ] :compressors A list of potential
217
224
  # compressors to use, in order of preference. The driver chooses the
218
225
  # first compressor that is also supported by the server. Currently the
@@ -309,7 +316,7 @@ module Mongo
309
316
  # for selecting a server for an operation.
310
317
  # @option options [ Float ] :socket_timeout The timeout, in seconds, to
311
318
  # execute operations on a socket.
312
- # @option options [ true, false ] :ssl Whether to use SSL.
319
+ # @option options [ true, false ] :ssl Whether to use TLS.
313
320
  # @option options [ String ] :ssl_ca_cert The file containing concatenated
314
321
  # certificate authority certificates used to validate certs passed from the
315
322
  # other end of the connection. Intermediate certificates should NOT be
@@ -370,6 +377,10 @@ module Mongo
370
377
  # @option options [ String ] :user The user name.
371
378
  # @option options [ Float ] :wait_queue_timeout The time to wait, in
372
379
  # seconds, in the connection pool for a connection to be checked in.
380
+ # @option options [ Array<Hash> ] :wrapping_libraries Information about
381
+ # libraries such as ODMs that are wrapping the driver, to be added to
382
+ # metadata sent to the server. Specify the lower level libraries first.
383
+ # Allowed hash keys: :name, :version, :platform.
373
384
  # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
374
385
  # option.
375
386
  # @option options [ Hash ] :write_concern The write concern options.
@@ -443,14 +454,39 @@ module Mongo
443
454
  @srv_records = uri.srv_records
444
455
  else
445
456
  addresses = addresses_or_uri
457
+ addresses.each do |addr|
458
+ if addr =~ /\Amongodb(\+srv)?:\/\//i
459
+ raise ArgumentError, "Host '#{addr}' should not contain protocol. Did you mean to not use an array?"
460
+ end
461
+ end
462
+
446
463
  @srv_records = nil
447
464
  end
448
465
 
466
+ options = self.class.canonicalize_ruby_options(options)
467
+
449
468
  # Special handling for sdam_proc as it is only used during client
450
469
  # construction
451
470
  sdam_proc = options.delete(:sdam_proc)
452
471
 
453
- options = default_options(options).merge(options)
472
+ # For gssapi service_name, the default option is given in a hash
473
+ # (one level down from the top level).
474
+ merged_options = default_options(options)
475
+ options.each do |k, v|
476
+ default_v = merged_options[k]
477
+ if Hash === default_v
478
+ v = default_v.merge(v)
479
+ end
480
+ merged_options[k] = v
481
+ end
482
+ options = merged_options
483
+
484
+ options.keys.each do |k|
485
+ if options[k].nil?
486
+ options.delete(k)
487
+ end
488
+ end
489
+
454
490
  @options = validate_new_options!(options)
455
491
  =begin WriteConcern object support
456
492
  if @options[:write_concern].is_a?(WriteConcern::Base)
@@ -489,7 +525,6 @@ module Mongo
489
525
  end
490
526
  end
491
527
 
492
- yield(self) if block_given?
493
528
  rescue
494
529
  begin
495
530
  @cluster.disconnect!
@@ -499,6 +534,14 @@ module Mongo
499
534
  end
500
535
  raise
501
536
  end
537
+
538
+ if block_given?
539
+ begin
540
+ yield(self)
541
+ ensure
542
+ close
543
+ end
544
+ end
502
545
  end
503
546
 
504
547
  # @api private
@@ -571,15 +614,12 @@ module Mongo
571
614
 
572
615
  # Get a summary of the client state.
573
616
  #
574
- # @note This method is experimental and subject to change.
575
- #
576
- # @example Inspect the client.
577
- # client.summary
617
+ # @note The exact format and layout of the returned summary string is
618
+ # not part of the driver's public API and may be changed at any time.
578
619
  #
579
- # @return [ String ] Summary string.
620
+ # @return [ String ] The summary string.
580
621
  #
581
622
  # @since 2.7.0
582
- # @api experimental
583
623
  def summary
584
624
  "#<Client cluster=#{cluster.summary}>"
585
625
  end
@@ -609,7 +649,7 @@ module Mongo
609
649
  #
610
650
  # @return [ BSON::Document ] The user-defined read preference.
611
651
  # The document may have the following fields:
612
- # - *:read* -- read preference specified as a symbol; valid values are
652
+ # - *:mode* -- read preference specified as a symbol; valid values are
613
653
  # *:primary*, *:primary_preferred*, *:secondary*, *:secondary_preferred*
614
654
  # and *:nearest*.
615
655
  # - *:tag_sets* -- an array of hashes.
@@ -735,7 +775,6 @@ module Mongo
735
775
  options[:read_concern]
736
776
  end
737
777
 
738
-
739
778
  # Get the write concern for this client. If no option was provided, then a
740
779
  # default single server acknowledgement will be used.
741
780
  #
@@ -802,6 +841,13 @@ module Mongo
802
841
  # @param [ Hash ] filter The filter criteria for getting a list of databases.
803
842
  # @param [ Hash ] opts The command options.
804
843
  #
844
+ # @option opts [ true, false ] :authorized_databases A flag that determines
845
+ # which databases are returned based on user privileges when access control
846
+ # is enabled
847
+ #
848
+ # See https://docs.mongodb.com/manual/reference/command/listDatabases/
849
+ # for more information and usage.
850
+ #
805
851
  # @return [ Array<String> ] The names of the databases.
806
852
  #
807
853
  # @since 2.0.5
@@ -818,6 +864,13 @@ module Mongo
818
864
  # @param [ true, false ] name_only Whether to only return each database name without full metadata.
819
865
  # @param [ Hash ] opts The command options.
820
866
  #
867
+ # @option opts [ true, false ] :authorized_databases A flag that determines
868
+ # which databases are returned based on user privileges when access control
869
+ # is enabled
870
+ #
871
+ # See https://docs.mongodb.com/manual/reference/command/listDatabases/
872
+ # for more information and usage.
873
+ #
821
874
  # @return [ Array<Hash> ] The info for each database.
822
875
  #
823
876
  # @since 2.0.5
@@ -825,6 +878,7 @@ module Mongo
825
878
  cmd = { listDatabases: 1 }
826
879
  cmd[:nameOnly] = !!name_only
827
880
  cmd[:filter] = filter unless filter.empty?
881
+ cmd[:authorizedDatabases] = true if opts[:authorized_databases]
828
882
  use(Database::ADMIN).database.read_command(cmd, opts).first[Database::DATABASES]
829
883
  end
830
884
 
@@ -865,8 +919,16 @@ module Mongo
865
919
  #
866
920
  # @since 2.5.0
867
921
  def start_session(options = {})
868
- get_session(options.merge(implicit: false)) or
869
- raise Error::InvalidSession.new(Session::SESSIONS_NOT_SUPPORTED)
922
+ session = get_session!(options.merge(implicit: false))
923
+ if block_given?
924
+ begin
925
+ yield session
926
+ ensure
927
+ session.end_session
928
+ end
929
+ else
930
+ session
931
+ end
870
932
  end
871
933
 
872
934
  # As of version 3.6 of the MongoDB server, a ``$changeStream`` pipeline stage is supported
@@ -912,6 +974,76 @@ module Mongo
912
974
  options)
913
975
  end
914
976
 
977
+ # Returns a session to use for operations if possible.
978
+ #
979
+ # If :session option is set, validates that session and returns it.
980
+ # Otherwise, if deployment supports sessions, creates a new session and
981
+ # returns it. When a new session is created, the session will be implicit
982
+ # (lifecycle is managed by the driver) if the :implicit option is given,
983
+ # otherwise the session will be explicit (lifecycle managed by the
984
+ # application). If deployment does not support session, returns nil.
985
+ #
986
+ # @option options [ true | false ] :implicit When no session is passed in,
987
+ # whether to create an implicit session.
988
+ # @option options [ Session ] :session The session to validate and return.
989
+ #
990
+ # @return [ Session | nil ] Session object or nil if sessions are not
991
+ # supported by the deployment.
992
+ #
993
+ # @api private
994
+ def get_session(options = {})
995
+ get_session!(options)
996
+ rescue Error::SessionsNotSupported
997
+ nil
998
+ end
999
+
1000
+ # Creates a session to use for operations if possible and yields it to
1001
+ # the provided block.
1002
+ #
1003
+ # If :session option is set, validates that session and uses it.
1004
+ # Otherwise, if deployment supports sessions, creates a new session and
1005
+ # uses it. When a new session is created, the session will be implicit
1006
+ # (lifecycle is managed by the driver) if the :implicit option is given,
1007
+ # otherwise the session will be explicit (lifecycle managed by the
1008
+ # application). If deployment does not support session, yields nil to
1009
+ # the block.
1010
+ #
1011
+ # When the block finishes, if the session was created and was implicit,
1012
+ # or if an implicit session was passed in, the session is ended which
1013
+ # returns it to the pool of available sessions.
1014
+ #
1015
+ # @option options [ true | false ] :implicit When no session is passed in,
1016
+ # whether to create an implicit session.
1017
+ # @option options [ Session ] :session The session to validate and return.
1018
+ #
1019
+ # @api private
1020
+ def with_session(options = {}, &block)
1021
+ session = get_session(options)
1022
+
1023
+ yield session
1024
+ ensure
1025
+ if session && session.implicit?
1026
+ session.end_session
1027
+ end
1028
+ end
1029
+
1030
+ class << self
1031
+ # Lowercases auth mechanism properties, if given, in the specified
1032
+ # options, then converts the options to an instance of Options::Redacted.
1033
+ #
1034
+ # @api private
1035
+ def canonicalize_ruby_options(options)
1036
+ Options::Redacted.new(Hash[options.map do |k, v|
1037
+ if k == :auth_mech_properties || k == 'auth_mech_properties'
1038
+ if v
1039
+ v = Hash[v.map { |pk, pv| [pk.downcase, pv] }]
1040
+ end
1041
+ end
1042
+ [k, v]
1043
+ end])
1044
+ end
1045
+ end
1046
+
915
1047
  private
916
1048
 
917
1049
  # Create a new encrypter object using the client's auto encryption options
@@ -944,30 +1076,34 @@ module Mongo
944
1076
  close_encrypter
945
1077
  end
946
1078
 
947
- # If options[:session] is set, validates that session and returns it.
948
- # If deployment supports sessions, creates a new session and returns it.
949
- # The session is implicit unless options[:implicit] is given.
950
- # If deployment does not support session, returns nil.
1079
+ # Returns a session to use for operations.
951
1080
  #
952
- # @return [ Session | nil ] Session object or nil if sessions are not
953
- # supported by the deployment.
954
- def get_session(options = {})
1081
+ # If :session option is set, validates that session and returns it.
1082
+ # Otherwise, if deployment supports sessions, creates a new session and
1083
+ # returns it. When a new session is created, the session will be implicit
1084
+ # (lifecycle is managed by the driver) if the :implicit option is given,
1085
+ # otherwise the session will be explicit (lifecycle managed by the
1086
+ # application). If deployment does not support session, raises
1087
+ # Error::InvalidSession.
1088
+ #
1089
+ # @option options [ true | false ] :implicit When no session is passed in,
1090
+ # whether to create an implicit session.
1091
+ # @option options [ Session ] :session The session to validate and return.
1092
+ #
1093
+ # @return [ Session ] A session object.
1094
+ #
1095
+ # @raise Error::SessionsNotSupported if sessions are not supported by
1096
+ # the deployment.
1097
+ #
1098
+ # @api private
1099
+ def get_session!(options = {})
955
1100
  if options[:session]
956
1101
  return options[:session].validate!(self)
957
1102
  end
958
1103
 
959
- if cluster.sessions_supported?
960
- Session.new(cluster.session_pool.checkout, self, { implicit: true }.merge(options))
961
- end
962
- end
1104
+ cluster.validate_session_support!
963
1105
 
964
- def with_session(options = {}, &block)
965
- session = get_session(options)
966
- yield(session)
967
- ensure
968
- if session && session.implicit?
969
- session.end_session
970
- end
1106
+ Session.new(cluster.session_pool.checkout, self, { implicit: true }.merge(options))
971
1107
  end
972
1108
 
973
1109
  def initialize_copy(original)
@@ -993,6 +1129,23 @@ module Mongo
993
1129
  # but does not check for interactions between combinations of options.
994
1130
  def validate_new_options!(opts = Options::Redacted.new)
995
1131
  return Options::Redacted.new unless opts
1132
+ if opts[:read_concern]
1133
+ # Raise an error for non user-settable options
1134
+ if opts[:read_concern][:after_cluster_time]
1135
+ raise Mongo::Error::InvalidReadConcern.new(
1136
+ 'The after_cluster_time read_concern option cannot be specified by the user'
1137
+ )
1138
+ end
1139
+
1140
+ given_keys = opts[:read_concern].keys.map(&:to_s)
1141
+ allowed_keys = ['level']
1142
+ invalid_keys = given_keys - allowed_keys
1143
+ # Warn that options are invalid but keep it and forward to the server
1144
+ unless invalid_keys.empty?
1145
+ log_warn("Read concern has invalid keys: #{invalid_keys.join(',')}.")
1146
+ end
1147
+ end
1148
+
996
1149
  Lint.validate_underscore_read_preference(opts[:read])
997
1150
  Lint.validate_read_concern_option(opts[:read_concern])
998
1151
  opts.each.inject(Options::Redacted.new) do |_options, (k, v)|
@@ -1038,6 +1191,60 @@ module Mongo
1038
1191
  if options[:direct_connection] == false && options[:connect] && options[:connect].to_sym == :direct
1039
1192
  raise ArgumentError, "Conflicting client options: direct_connection=false and connect=#{options[:connect]}"
1040
1193
  end
1194
+
1195
+ %i(connect_timeout socket_timeout).each do |key|
1196
+ if value = options[key]
1197
+ unless Numeric === value
1198
+ raise ArgumentError, "#{key} must be a non-negative number: #{value}"
1199
+ end
1200
+ if value < 0
1201
+ raise ArgumentError, "#{key} must be a non-negative number: #{value}"
1202
+ end
1203
+ end
1204
+ end
1205
+
1206
+ if value = options[:bg_error_backtrace]
1207
+ case value
1208
+ when Integer
1209
+ if value <= 0
1210
+ raise ArgumentError, ":bg_error_backtrace option value must be true, false, nil or a positive integer: #{value}"
1211
+ end
1212
+ when true
1213
+ # OK
1214
+ else
1215
+ raise ArgumentError, ":bg_error_backtrace option value must be true, false, nil or a positive integer: #{value}"
1216
+ end
1217
+ end
1218
+
1219
+ if libraries = options[:wrapping_libraries]
1220
+ unless Array === libraries
1221
+ raise ArgumentError, ":wrapping_libraries must be an array of hashes: #{libraries}"
1222
+ end
1223
+
1224
+ libraries = libraries.map do |library|
1225
+ Utils.shallow_symbolize_keys(library)
1226
+ end
1227
+
1228
+ libraries.each do |library|
1229
+ unless Hash === library
1230
+ raise ArgumentError, ":wrapping_libraries element is not a hash: #{library}"
1231
+ end
1232
+
1233
+ if library.empty?
1234
+ raise ArgumentError, ":wrapping_libraries element is empty"
1235
+ end
1236
+
1237
+ unless (library.keys - %i(name platform version)).empty?
1238
+ raise ArgumentError, ":wrapping_libraries element has invalid keys (allowed keys: :name, :platform, :version): #{library}"
1239
+ end
1240
+
1241
+ library.each do |key, value|
1242
+ if value.include?('|')
1243
+ raise ArgumentError, ":wrapping_libraries element value cannot include '|': #{value}"
1244
+ end
1245
+ end
1246
+ end
1247
+ end
1041
1248
  end
1042
1249
 
1043
1250
  # Validates all authentication-related options after they are set on the client