mongo 2.13.0.beta1 → 2.14.0

Sign up to get free protection for your applications and to get access to all the features.
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