mongo 2.18.2 → 2.19.3

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 (1153) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +12 -2
  4. data/Rakefile +4 -3
  5. data/bin/mongo_console +2 -0
  6. data/lib/mongo/active_support.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/address/unix.rb +1 -1
  10. data/lib/mongo/address/validator.rb +1 -1
  11. data/lib/mongo/address.rb +1 -1
  12. data/lib/mongo/auth/aws/conversation.rb +1 -5
  13. data/lib/mongo/auth/aws/credentials.rb +38 -0
  14. data/lib/mongo/auth/aws/credentials_cache.rb +75 -0
  15. data/lib/mongo/auth/aws/credentials_retriever.rb +172 -37
  16. data/lib/mongo/auth/aws/request.rb +1 -2
  17. data/lib/mongo/auth/aws.rb +6 -6
  18. data/lib/mongo/auth/base.rb +1 -1
  19. data/lib/mongo/auth/conversation_base.rb +1 -1
  20. data/lib/mongo/auth/cr/conversation.rb +1 -1
  21. data/lib/mongo/auth/cr.rb +1 -1
  22. data/lib/mongo/auth/credential_cache.rb +1 -1
  23. data/lib/mongo/auth/gssapi/conversation.rb +1 -1
  24. data/lib/mongo/auth/gssapi.rb +1 -1
  25. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  26. data/lib/mongo/auth/ldap.rb +1 -1
  27. data/lib/mongo/auth/roles.rb +17 -17
  28. data/lib/mongo/auth/sasl_conversation_base.rb +1 -1
  29. data/lib/mongo/auth/scram/conversation.rb +1 -1
  30. data/lib/mongo/auth/scram.rb +1 -1
  31. data/lib/mongo/auth/scram256/conversation.rb +1 -1
  32. data/lib/mongo/auth/scram256.rb +1 -1
  33. data/lib/mongo/auth/scram_conversation_base.rb +1 -1
  34. data/lib/mongo/auth/stringprep/profiles/sasl.rb +1 -1
  35. data/lib/mongo/auth/stringprep/tables.rb +1 -1
  36. data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +1 -1
  37. data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +2 -1
  38. data/lib/mongo/auth/stringprep.rb +1 -1
  39. data/lib/mongo/auth/user/view.rb +1 -1
  40. data/lib/mongo/auth/user.rb +1 -1
  41. data/lib/mongo/auth/x509/conversation.rb +1 -1
  42. data/lib/mongo/auth/x509.rb +1 -1
  43. data/lib/mongo/auth.rb +1 -1
  44. data/lib/mongo/background_thread.rb +1 -1
  45. data/lib/mongo/bson.rb +1 -1
  46. data/lib/mongo/bulk_write/combineable.rb +1 -1
  47. data/lib/mongo/bulk_write/ordered_combiner.rb +1 -1
  48. data/lib/mongo/bulk_write/result.rb +1 -1
  49. data/lib/mongo/bulk_write/result_combiner.rb +1 -1
  50. data/lib/mongo/bulk_write/transformable.rb +1 -1
  51. data/lib/mongo/bulk_write/unordered_combiner.rb +1 -1
  52. data/lib/mongo/bulk_write/validatable.rb +1 -1
  53. data/lib/mongo/bulk_write.rb +1 -1
  54. data/lib/mongo/caching_cursor.rb +1 -1
  55. data/lib/mongo/client.rb +52 -4
  56. data/lib/mongo/client_encryption.rb +102 -1
  57. data/lib/mongo/cluster/periodic_executor.rb +1 -1
  58. data/lib/mongo/cluster/reapers/cursor_reaper.rb +2 -6
  59. data/lib/mongo/cluster/reapers/socket_reaper.rb +2 -2
  60. data/lib/mongo/cluster/sdam_flow.rb +42 -15
  61. data/lib/mongo/cluster/topology/base.rb +1 -1
  62. data/lib/mongo/cluster/topology/load_balanced.rb +1 -1
  63. data/lib/mongo/cluster/topology/no_replica_set_options.rb +1 -1
  64. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  65. data/lib/mongo/cluster/topology/replica_set_with_primary.rb +1 -1
  66. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  67. data/lib/mongo/cluster/topology/single.rb +1 -1
  68. data/lib/mongo/cluster/topology/unknown.rb +1 -1
  69. data/lib/mongo/cluster/topology.rb +1 -1
  70. data/lib/mongo/cluster.rb +29 -12
  71. data/lib/mongo/cluster_time.rb +1 -1
  72. data/lib/mongo/collection/helpers.rb +1 -1
  73. data/lib/mongo/collection/queryable_encryption.rb +83 -43
  74. data/lib/mongo/collection/view/aggregation.rb +1 -1
  75. data/lib/mongo/collection/view/builder/aggregation.rb +1 -1
  76. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  77. data/lib/mongo/collection/view/builder.rb +1 -1
  78. data/lib/mongo/collection/view/change_stream/retryable.rb +1 -1
  79. data/lib/mongo/collection/view/change_stream.rb +3 -3
  80. data/lib/mongo/collection/view/explainable.rb +1 -1
  81. data/lib/mongo/collection/view/immutable.rb +1 -1
  82. data/lib/mongo/collection/view/iterable.rb +16 -1
  83. data/lib/mongo/collection/view/map_reduce.rb +1 -1
  84. data/lib/mongo/collection/view/readable.rb +11 -12
  85. data/lib/mongo/collection/view/writable.rb +1 -1
  86. data/lib/mongo/collection/view.rb +2 -1
  87. data/lib/mongo/collection.rb +52 -13
  88. data/lib/mongo/condition_variable.rb +58 -0
  89. data/lib/mongo/config/options.rb +1 -0
  90. data/lib/mongo/config/validators/option.rb +1 -0
  91. data/lib/mongo/config.rb +1 -0
  92. data/lib/mongo/crypt/auto_decryption_context.rb +1 -1
  93. data/lib/mongo/crypt/auto_encrypter.rb +5 -3
  94. data/lib/mongo/crypt/auto_encryption_context.rb +1 -1
  95. data/lib/mongo/crypt/binary.rb +1 -1
  96. data/lib/mongo/crypt/binding.rb +224 -30
  97. data/lib/mongo/crypt/context.rb +67 -4
  98. data/lib/mongo/crypt/data_key_context.rb +1 -1
  99. data/lib/mongo/crypt/encryption_io.rb +2 -2
  100. data/lib/mongo/crypt/explicit_decryption_context.rb +1 -1
  101. data/lib/mongo/crypt/explicit_encrypter.rb +120 -34
  102. data/lib/mongo/crypt/explicit_encryption_context.rb +58 -27
  103. data/lib/mongo/crypt/explicit_encryption_expression_context.rb +30 -0
  104. data/lib/mongo/crypt/handle.rb +10 -2
  105. data/lib/mongo/crypt/hooks.rb +1 -1
  106. data/lib/mongo/crypt/kms/aws/credentials.rb +83 -0
  107. data/lib/mongo/crypt/kms/aws/master_document.rb +78 -0
  108. data/lib/mongo/crypt/kms/aws.rb +3 -119
  109. data/lib/mongo/crypt/kms/azure/access_token.rb +54 -0
  110. data/lib/mongo/crypt/kms/azure/credentials.rb +103 -0
  111. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +122 -0
  112. data/lib/mongo/crypt/kms/azure/master_document.rb +79 -0
  113. data/lib/mongo/crypt/kms/azure.rb +5 -128
  114. data/lib/mongo/crypt/kms/credentials.rb +17 -2
  115. data/lib/mongo/crypt/kms/gcp/credentials.rb +127 -0
  116. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +58 -0
  117. data/lib/mongo/crypt/kms/gcp/master_document.rb +99 -0
  118. data/lib/mongo/crypt/kms/gcp.rb +4 -172
  119. data/lib/mongo/crypt/kms/kmip/credentials.rb +68 -0
  120. data/lib/mongo/crypt/kms/kmip/master_document.rb +74 -0
  121. data/lib/mongo/crypt/kms/kmip.rb +3 -100
  122. data/lib/mongo/crypt/kms/local/credentials.rb +65 -0
  123. data/lib/mongo/crypt/kms/local/master_document.rb +43 -0
  124. data/lib/mongo/crypt/kms/local.rb +3 -66
  125. data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
  126. data/lib/mongo/crypt/kms.rb +7 -1
  127. data/lib/mongo/crypt/kms_context.rb +1 -1
  128. data/lib/mongo/crypt/rewrap_many_data_key_context.rb +1 -1
  129. data/lib/mongo/crypt/rewrap_many_data_key_result.rb +1 -1
  130. data/lib/mongo/crypt/status.rb +1 -1
  131. data/lib/mongo/crypt.rb +13 -1
  132. data/lib/mongo/cursor/kill_spec.rb +1 -1
  133. data/lib/mongo/cursor.rb +40 -6
  134. data/lib/mongo/database/view.rb +41 -4
  135. data/lib/mongo/database.rb +2 -2
  136. data/lib/mongo/dbref.rb +1 -1
  137. data/lib/mongo/distinguishing_semaphore.rb +2 -2
  138. data/lib/mongo/error/auth_error.rb +1 -1
  139. data/lib/mongo/error/bad_load_balancer_target.rb +1 -1
  140. data/lib/mongo/error/bulk_write_error.rb +1 -1
  141. data/lib/mongo/error/change_stream_resumable.rb +1 -1
  142. data/lib/mongo/error/client_closed.rb +24 -0
  143. data/lib/mongo/error/closed_stream.rb +1 -1
  144. data/lib/mongo/error/connection_check_out_timeout.rb +1 -1
  145. data/lib/mongo/error/connection_perished.rb +3 -1
  146. data/lib/mongo/error/connection_unavailable.rb +27 -0
  147. data/lib/mongo/error/credential_check_error.rb +1 -1
  148. data/lib/mongo/error/crypt_error.rb +1 -1
  149. data/lib/mongo/error/extra_file_chunk.rb +1 -1
  150. data/lib/mongo/error/failed_string_prep_validation.rb +1 -1
  151. data/lib/mongo/error/file_not_found.rb +1 -1
  152. data/lib/mongo/error/handshake_error.rb +1 -1
  153. data/lib/mongo/error/insufficient_iteration_count.rb +1 -1
  154. data/lib/mongo/error/internal_driver_error.rb +1 -1
  155. data/lib/mongo/error/invalid_address.rb +1 -1
  156. data/lib/mongo/error/invalid_application_name.rb +1 -1
  157. data/lib/mongo/error/invalid_bulk_operation.rb +1 -1
  158. data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -1
  159. data/lib/mongo/error/invalid_collection_name.rb +1 -1
  160. data/lib/mongo/error/invalid_config_option.rb +1 -0
  161. data/lib/mongo/error/invalid_cursor_operation.rb +1 -1
  162. data/lib/mongo/error/invalid_database_name.rb +1 -1
  163. data/lib/mongo/error/invalid_document.rb +1 -1
  164. data/lib/mongo/error/invalid_file.rb +1 -1
  165. data/lib/mongo/error/invalid_file_revision.rb +1 -1
  166. data/lib/mongo/error/invalid_max_connecting.rb +28 -0
  167. data/lib/mongo/error/invalid_min_pool_size.rb +1 -1
  168. data/lib/mongo/error/invalid_nonce.rb +1 -1
  169. data/lib/mongo/error/invalid_read_concern.rb +1 -1
  170. data/lib/mongo/error/invalid_read_option.rb +1 -1
  171. data/lib/mongo/error/invalid_replacement_document.rb +1 -1
  172. data/lib/mongo/error/invalid_server_auth_host.rb +1 -1
  173. data/lib/mongo/error/invalid_server_auth_response.rb +1 -1
  174. data/lib/mongo/error/invalid_server_preference.rb +1 -1
  175. data/lib/mongo/error/invalid_session.rb +1 -1
  176. data/lib/mongo/error/invalid_signature.rb +1 -1
  177. data/lib/mongo/error/invalid_transaction_operation.rb +1 -1
  178. data/lib/mongo/error/invalid_txt_record.rb +1 -1
  179. data/lib/mongo/error/invalid_update_document.rb +1 -1
  180. data/lib/mongo/error/invalid_uri.rb +1 -1
  181. data/lib/mongo/error/invalid_write_concern.rb +1 -1
  182. data/lib/mongo/error/kms_error.rb +1 -1
  183. data/lib/mongo/error/labelable.rb +1 -1
  184. data/lib/mongo/error/lint_error.rb +1 -1
  185. data/lib/mongo/error/max_bson_size.rb +1 -1
  186. data/lib/mongo/error/max_message_size.rb +1 -1
  187. data/lib/mongo/error/mismatched_domain.rb +1 -1
  188. data/lib/mongo/error/missing_connection.rb +4 -2
  189. data/lib/mongo/error/missing_file_chunk.rb +1 -1
  190. data/lib/mongo/error/missing_password.rb +1 -1
  191. data/lib/mongo/error/missing_resume_token.rb +1 -1
  192. data/lib/mongo/error/missing_scram_server_signature.rb +1 -1
  193. data/lib/mongo/error/missing_service_id.rb +1 -1
  194. data/lib/mongo/error/mongocryptd_spawn_error.rb +1 -1
  195. data/lib/mongo/error/multi_index_drop.rb +1 -1
  196. data/lib/mongo/error/need_primary_server.rb +1 -1
  197. data/lib/mongo/error/no_server_available.rb +1 -1
  198. data/lib/mongo/error/no_service_connection_available.rb +1 -1
  199. data/lib/mongo/error/no_srv_records.rb +1 -1
  200. data/lib/mongo/error/notable.rb +8 -1
  201. data/lib/mongo/error/operation_failure.rb +1 -1
  202. data/lib/mongo/error/parser.rb +1 -1
  203. data/lib/mongo/error/pool_cleared_error.rb +40 -0
  204. data/lib/mongo/error/pool_closed_error.rb +4 -17
  205. data/lib/mongo/error/pool_error.rb +45 -0
  206. data/lib/mongo/error/pool_paused_error.rb +40 -0
  207. data/lib/mongo/error/raise_original_error.rb +1 -1
  208. data/lib/mongo/error/read_write_retryable.rb +1 -1
  209. data/lib/mongo/error/sdam_error_detection.rb +1 -1
  210. data/lib/mongo/error/server_api_conflict.rb +1 -1
  211. data/lib/mongo/error/server_api_not_supported.rb +1 -1
  212. data/lib/mongo/error/server_certificate_revoked.rb +1 -1
  213. data/lib/mongo/error/server_not_usable.rb +36 -0
  214. data/lib/mongo/error/session_ended.rb +1 -1
  215. data/lib/mongo/error/session_not_materialized.rb +1 -1
  216. data/lib/mongo/error/sessions_not_supported.rb +1 -1
  217. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +1 -1
  218. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +1 -1
  219. data/lib/mongo/error/socket_error.rb +1 -1
  220. data/lib/mongo/error/socket_timeout_error.rb +1 -1
  221. data/lib/mongo/error/unchangeable_collection_option.rb +1 -1
  222. data/lib/mongo/error/unexpected_chunk_length.rb +1 -1
  223. data/lib/mongo/error/unexpected_response.rb +1 -1
  224. data/lib/mongo/error/unknown_payload_type.rb +1 -1
  225. data/lib/mongo/error/unmet_dependency.rb +1 -1
  226. data/lib/mongo/error/unsupported_array_filters.rb +1 -1
  227. data/lib/mongo/error/unsupported_collation.rb +1 -1
  228. data/lib/mongo/error/unsupported_features.rb +1 -1
  229. data/lib/mongo/error/unsupported_message_type.rb +1 -1
  230. data/lib/mongo/error/unsupported_option.rb +1 -1
  231. data/lib/mongo/error/write_retryable.rb +1 -1
  232. data/lib/mongo/error.rb +8 -1
  233. data/lib/mongo/event/base.rb +1 -1
  234. data/lib/mongo/event/listeners.rb +1 -1
  235. data/lib/mongo/event/publisher.rb +1 -1
  236. data/lib/mongo/event/subscriber.rb +1 -1
  237. data/lib/mongo/event.rb +1 -1
  238. data/lib/mongo/grid/file/chunk.rb +3 -2
  239. data/lib/mongo/grid/file/info.rb +3 -2
  240. data/lib/mongo/grid/file.rb +1 -1
  241. data/lib/mongo/grid/fs_bucket.rb +1 -1
  242. data/lib/mongo/grid/stream/read.rb +1 -1
  243. data/lib/mongo/grid/stream/write.rb +1 -1
  244. data/lib/mongo/grid/stream.rb +1 -1
  245. data/lib/mongo/grid.rb +1 -1
  246. data/lib/mongo/id.rb +1 -1
  247. data/lib/mongo/index/view.rb +1 -1
  248. data/lib/mongo/index.rb +1 -1
  249. data/lib/mongo/lint.rb +1 -1
  250. data/lib/mongo/loggable.rb +3 -3
  251. data/lib/mongo/logger.rb +1 -1
  252. data/lib/mongo/monitoring/cmap_log_subscriber.rb +1 -1
  253. data/lib/mongo/monitoring/command_log_subscriber.rb +1 -1
  254. data/lib/mongo/monitoring/event/cmap/base.rb +1 -1
  255. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
  256. data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +1 -1
  257. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +1 -1
  258. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +1 -1
  259. data/lib/mongo/monitoring/event/cmap/connection_closed.rb +1 -1
  260. data/lib/mongo/monitoring/event/cmap/connection_created.rb +1 -1
  261. data/lib/mongo/monitoring/event/cmap/connection_ready.rb +1 -1
  262. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +9 -2
  263. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +1 -1
  264. data/lib/mongo/monitoring/event/cmap/pool_created.rb +1 -1
  265. data/lib/mongo/monitoring/event/cmap/pool_ready.rb +67 -0
  266. data/lib/mongo/monitoring/event/cmap.rb +2 -1
  267. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  268. data/lib/mongo/monitoring/event/command_started.rb +1 -1
  269. data/lib/mongo/monitoring/event/command_succeeded.rb +1 -1
  270. data/lib/mongo/monitoring/event/secure.rb +1 -1
  271. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  272. data/lib/mongo/monitoring/event/server_description_changed.rb +1 -1
  273. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +1 -1
  274. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +1 -1
  275. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +1 -1
  276. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  277. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  278. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  279. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  280. data/lib/mongo/monitoring/event.rb +1 -1
  281. data/lib/mongo/monitoring/publishable.rb +1 -1
  282. data/lib/mongo/monitoring/sdam_log_subscriber.rb +1 -1
  283. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +1 -1
  284. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +1 -1
  285. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +1 -1
  286. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  287. data/lib/mongo/monitoring/topology_closed_log_subscriber.rb +1 -1
  288. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +1 -1
  289. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +1 -1
  290. data/lib/mongo/monitoring.rb +1 -1
  291. data/lib/mongo/operation/aggregate/op_msg.rb +1 -1
  292. data/lib/mongo/operation/aggregate/result.rb +1 -1
  293. data/lib/mongo/operation/aggregate.rb +1 -1
  294. data/lib/mongo/operation/collections_info/result.rb +1 -1
  295. data/lib/mongo/operation/collections_info.rb +1 -1
  296. data/lib/mongo/operation/command/op_msg.rb +1 -1
  297. data/lib/mongo/operation/command.rb +1 -1
  298. data/lib/mongo/operation/context.rb +1 -1
  299. data/lib/mongo/operation/count/op_msg.rb +1 -1
  300. data/lib/mongo/operation/count.rb +1 -1
  301. data/lib/mongo/operation/create/op_msg.rb +1 -1
  302. data/lib/mongo/operation/create.rb +1 -1
  303. data/lib/mongo/operation/create_index/op_msg.rb +1 -1
  304. data/lib/mongo/operation/create_index.rb +1 -1
  305. data/lib/mongo/operation/create_search_indexes/op_msg.rb +31 -0
  306. data/lib/mongo/operation/create_search_indexes.rb +15 -0
  307. data/lib/mongo/operation/create_user/op_msg.rb +1 -1
  308. data/lib/mongo/operation/create_user.rb +1 -1
  309. data/lib/mongo/operation/delete/bulk_result.rb +1 -1
  310. data/lib/mongo/operation/delete/op_msg.rb +1 -1
  311. data/lib/mongo/operation/delete/result.rb +1 -1
  312. data/lib/mongo/operation/delete.rb +1 -1
  313. data/lib/mongo/operation/distinct/op_msg.rb +1 -1
  314. data/lib/mongo/operation/distinct.rb +1 -1
  315. data/lib/mongo/operation/drop/op_msg.rb +1 -1
  316. data/lib/mongo/operation/drop.rb +1 -1
  317. data/lib/mongo/operation/drop_database/op_msg.rb +1 -1
  318. data/lib/mongo/operation/drop_database.rb +1 -1
  319. data/lib/mongo/operation/drop_index/op_msg.rb +1 -1
  320. data/lib/mongo/operation/drop_index.rb +1 -1
  321. data/lib/mongo/operation/drop_search_index/op_msg.rb +33 -0
  322. data/lib/mongo/operation/drop_search_index.rb +15 -0
  323. data/lib/mongo/operation/explain/op_msg.rb +1 -1
  324. data/lib/mongo/operation/explain/result.rb +1 -1
  325. data/lib/mongo/operation/explain.rb +1 -1
  326. data/lib/mongo/operation/find/builder/command.rb +1 -1
  327. data/lib/mongo/operation/find/builder/flags.rb +1 -1
  328. data/lib/mongo/operation/find/builder/modifiers.rb +1 -1
  329. data/lib/mongo/operation/find/builder.rb +1 -1
  330. data/lib/mongo/operation/find/op_msg.rb +1 -1
  331. data/lib/mongo/operation/find/result.rb +1 -1
  332. data/lib/mongo/operation/find.rb +1 -1
  333. data/lib/mongo/operation/get_more/command_builder.rb +1 -1
  334. data/lib/mongo/operation/get_more/op_msg.rb +1 -1
  335. data/lib/mongo/operation/get_more/result.rb +1 -1
  336. data/lib/mongo/operation/get_more.rb +1 -1
  337. data/lib/mongo/operation/indexes/op_msg.rb +1 -1
  338. data/lib/mongo/operation/indexes/result.rb +1 -1
  339. data/lib/mongo/operation/indexes.rb +1 -1
  340. data/lib/mongo/operation/insert/bulk_result.rb +1 -1
  341. data/lib/mongo/operation/insert/op_msg.rb +1 -1
  342. data/lib/mongo/operation/insert/result.rb +1 -1
  343. data/lib/mongo/operation/insert.rb +1 -1
  344. data/lib/mongo/operation/kill_cursors/command_builder.rb +1 -1
  345. data/lib/mongo/operation/kill_cursors/op_msg.rb +1 -1
  346. data/lib/mongo/operation/kill_cursors.rb +1 -1
  347. data/lib/mongo/operation/list_collections/op_msg.rb +1 -1
  348. data/lib/mongo/operation/list_collections/result.rb +1 -1
  349. data/lib/mongo/operation/list_collections.rb +1 -1
  350. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  351. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  352. data/lib/mongo/operation/map_reduce.rb +1 -1
  353. data/lib/mongo/operation/op_msg_base.rb +1 -1
  354. data/lib/mongo/operation/parallel_scan/op_msg.rb +1 -1
  355. data/lib/mongo/operation/parallel_scan/result.rb +1 -1
  356. data/lib/mongo/operation/parallel_scan.rb +1 -1
  357. data/lib/mongo/operation/remove_user/op_msg.rb +1 -1
  358. data/lib/mongo/operation/remove_user.rb +1 -1
  359. data/lib/mongo/operation/result.rb +1 -1
  360. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -1
  361. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -1
  362. data/lib/mongo/operation/shared/executable.rb +1 -1
  363. data/lib/mongo/operation/shared/executable_no_validate.rb +1 -1
  364. data/lib/mongo/operation/shared/executable_transaction_label.rb +1 -1
  365. data/lib/mongo/operation/shared/idable.rb +1 -1
  366. data/lib/mongo/operation/shared/limited.rb +1 -1
  367. data/lib/mongo/operation/shared/object_id_generator.rb +1 -1
  368. data/lib/mongo/operation/shared/op_msg_executable.rb +1 -1
  369. data/lib/mongo/operation/shared/polymorphic_lookup.rb +1 -1
  370. data/lib/mongo/operation/shared/polymorphic_result.rb +1 -1
  371. data/lib/mongo/operation/shared/read_preference_supported.rb +1 -1
  372. data/lib/mongo/operation/shared/response_handling.rb +1 -1
  373. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -1
  374. data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +1 -1
  375. data/lib/mongo/operation/shared/sessions_supported.rb +1 -2
  376. data/lib/mongo/operation/shared/specifiable.rb +8 -1
  377. data/lib/mongo/operation/shared/validatable.rb +1 -1
  378. data/lib/mongo/operation/shared/write.rb +1 -1
  379. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -1
  380. data/lib/mongo/operation/update/bulk_result.rb +1 -1
  381. data/lib/mongo/operation/update/op_msg.rb +1 -1
  382. data/lib/mongo/operation/update/result.rb +1 -1
  383. data/lib/mongo/operation/update.rb +1 -1
  384. data/lib/mongo/operation/update_search_index/op_msg.rb +34 -0
  385. data/lib/mongo/operation/update_search_index.rb +15 -0
  386. data/lib/mongo/operation/update_user/op_msg.rb +1 -1
  387. data/lib/mongo/operation/update_user.rb +1 -1
  388. data/lib/mongo/operation/users_info/op_msg.rb +1 -1
  389. data/lib/mongo/operation/users_info/result.rb +1 -1
  390. data/lib/mongo/operation/users_info.rb +1 -1
  391. data/lib/mongo/operation/write_command/op_msg.rb +1 -1
  392. data/lib/mongo/operation/write_command.rb +1 -1
  393. data/lib/mongo/operation.rb +4 -1
  394. data/lib/mongo/options/mapper.rb +1 -1
  395. data/lib/mongo/options/redacted.rb +1 -1
  396. data/lib/mongo/options.rb +1 -1
  397. data/lib/mongo/protocol/bit_vector.rb +4 -2
  398. data/lib/mongo/protocol/caching_hash.rb +4 -21
  399. data/lib/mongo/protocol/compressed.rb +1 -1
  400. data/lib/mongo/protocol/get_more.rb +1 -1
  401. data/lib/mongo/protocol/kill_cursors.rb +1 -1
  402. data/lib/mongo/protocol/message.rb +5 -9
  403. data/lib/mongo/protocol/msg.rb +2 -1
  404. data/lib/mongo/protocol/query.rb +1 -1
  405. data/lib/mongo/protocol/registry.rb +1 -1
  406. data/lib/mongo/protocol/reply.rb +1 -1
  407. data/lib/mongo/protocol/serializers.rb +25 -18
  408. data/lib/mongo/protocol.rb +1 -1
  409. data/lib/mongo/query_cache.rb +1 -1
  410. data/lib/mongo/retryable/base_worker.rb +91 -0
  411. data/lib/mongo/retryable/read_worker.rb +296 -0
  412. data/lib/mongo/retryable/write_worker.rb +364 -0
  413. data/lib/mongo/retryable.rb +31 -502
  414. data/lib/mongo/search_index/view.rb +232 -0
  415. data/lib/mongo/semaphore.rb +2 -2
  416. data/lib/mongo/server/app_metadata/environment.rb +259 -0
  417. data/lib/mongo/server/app_metadata/platform.rb +114 -0
  418. data/lib/mongo/server/app_metadata/truncator.rb +142 -0
  419. data/lib/mongo/server/app_metadata.rb +75 -108
  420. data/lib/mongo/server/connection.rb +61 -20
  421. data/lib/mongo/server/connection_base.rb +1 -1
  422. data/lib/mongo/server/connection_common.rb +1 -1
  423. data/lib/mongo/server/connection_pool/generation_manager.rb +56 -12
  424. data/lib/mongo/server/connection_pool/populator.rb +33 -31
  425. data/lib/mongo/server/connection_pool.rb +726 -265
  426. data/lib/mongo/server/description/features.rb +2 -2
  427. data/lib/mongo/server/description/load_balancer.rb +1 -1
  428. data/lib/mongo/server/description.rb +7 -6
  429. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  430. data/lib/mongo/server/monitor/connection.rb +1 -1
  431. data/lib/mongo/server/monitor.rb +11 -7
  432. data/lib/mongo/server/pending_connection.rb +1 -1
  433. data/lib/mongo/server/push_monitor/connection.rb +1 -1
  434. data/lib/mongo/server/push_monitor.rb +1 -1
  435. data/lib/mongo/server/round_trip_time_averager.rb +1 -1
  436. data/lib/mongo/server.rb +96 -30
  437. data/lib/mongo/server_selector/base.rb +24 -3
  438. data/lib/mongo/server_selector/nearest.rb +1 -1
  439. data/lib/mongo/server_selector/primary.rb +1 -1
  440. data/lib/mongo/server_selector/primary_preferred.rb +1 -1
  441. data/lib/mongo/server_selector/secondary.rb +1 -1
  442. data/lib/mongo/server_selector/secondary_preferred.rb +1 -1
  443. data/lib/mongo/server_selector.rb +1 -1
  444. data/lib/mongo/session/server_session.rb +1 -1
  445. data/lib/mongo/session/session_pool.rb +1 -1
  446. data/lib/mongo/session.rb +1 -1
  447. data/lib/mongo/socket/ocsp_cache.rb +1 -1
  448. data/lib/mongo/socket/ocsp_verifier.rb +1 -1
  449. data/lib/mongo/socket/ssl.rb +1 -1
  450. data/lib/mongo/socket/tcp.rb +1 -1
  451. data/lib/mongo/socket/unix.rb +1 -1
  452. data/lib/mongo/socket.rb +29 -2
  453. data/lib/mongo/srv/monitor.rb +1 -3
  454. data/lib/mongo/srv/resolver.rb +1 -1
  455. data/lib/mongo/srv/result.rb +1 -1
  456. data/lib/mongo/srv.rb +1 -1
  457. data/lib/mongo/timeout.rb +2 -2
  458. data/lib/mongo/topology_version.rb +1 -1
  459. data/lib/mongo/uri/options_mapper.rb +322 -81
  460. data/lib/mongo/uri/srv_protocol.rb +1 -1
  461. data/lib/mongo/uri.rb +41 -13
  462. data/lib/mongo/utils.rb +1 -1
  463. data/lib/mongo/version.rb +2 -2
  464. data/lib/mongo/write_concern/acknowledged.rb +1 -1
  465. data/lib/mongo/write_concern/base.rb +1 -1
  466. data/lib/mongo/write_concern/unacknowledged.rb +1 -1
  467. data/lib/mongo/write_concern.rb +1 -1
  468. data/lib/mongo.rb +3 -1
  469. data/mongo.gemspec +5 -2
  470. data/spec/atlas/atlas_connectivity_spec.rb +2 -6
  471. data/spec/atlas/operations_spec.rb +4 -13
  472. data/spec/integration/auth_spec.rb +1 -1
  473. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  474. data/spec/integration/aws_auth_credentials_cache_spec.rb +51 -0
  475. data/spec/integration/aws_auth_request_spec.rb +2 -2
  476. data/spec/integration/aws_credentials_retriever_spec.rb +32 -2
  477. data/spec/integration/aws_lambda_examples_spec.rb +1 -1
  478. data/spec/integration/bson_symbol_spec.rb +1 -1
  479. data/spec/integration/bulk_insert_spec.rb +1 -1
  480. data/spec/integration/bulk_write_error_message_spec.rb +1 -0
  481. data/spec/integration/bulk_write_spec.rb +1 -1
  482. data/spec/integration/change_stream_examples_spec.rb +1 -1
  483. data/spec/integration/change_stream_spec.rb +6 -1
  484. data/spec/integration/check_clean_slate_spec.rb +1 -1
  485. data/spec/integration/client_authentication_options_spec.rb +1 -1
  486. data/spec/integration/client_connectivity_spec.rb +1 -1
  487. data/spec/integration/client_construction_aws_auth_spec.rb +12 -3
  488. data/spec/integration/client_construction_spec.rb +23 -1
  489. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  490. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  491. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +1 -1
  492. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +1 -1
  493. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +10 -5
  494. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +38 -2
  495. data/spec/integration/client_side_encryption/automatic_data_encryption_keys_prose_spec.rb +153 -0
  496. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  497. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +1 -1
  498. data/spec/integration/client_side_encryption/client_close_spec.rb +1 -1
  499. data/spec/integration/client_side_encryption/corpus_spec.rb +1 -1
  500. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +3 -3
  501. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  502. data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +59 -58
  503. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +1 -1
  504. data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +36 -33
  505. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +1 -1
  506. data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +3 -3
  507. data/spec/integration/client_side_encryption/kms_tls_spec.rb +1 -1
  508. data/spec/integration/client_side_encryption/mongocryptd_prose_spec.rb +105 -0
  509. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +49 -0
  510. data/spec/integration/client_side_encryption/on_demand_azure_credentials_spec.rb +46 -0
  511. data/spec/integration/client_side_encryption/on_demand_gcp_credentials_spec.rb +47 -0
  512. data/spec/integration/client_side_encryption/queryable_encryption_examples_spec.rb +14 -11
  513. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +536 -0
  514. data/spec/integration/client_side_encryption/rewrap_prose_spec.rb +114 -0
  515. data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +20 -16
  516. data/spec/integration/client_side_encryption/views_spec.rb +1 -1
  517. data/spec/integration/client_spec.rb +8 -3
  518. data/spec/integration/client_update_spec.rb +7 -3
  519. data/spec/integration/collection_indexes_prose_spec.rb +1 -1
  520. data/spec/integration/command_monitoring_spec.rb +1 -1
  521. data/spec/integration/command_spec.rb +1 -1
  522. data/spec/integration/connect_single_rs_name_spec.rb +1 -1
  523. data/spec/integration/connection/faas_env_spec.rb +62 -0
  524. data/spec/integration/connection_pool_populator_spec.rb +27 -7
  525. data/spec/integration/connection_spec.rb +1 -1
  526. data/spec/integration/crud_spec.rb +1 -1
  527. data/spec/integration/cursor_pinning_spec.rb +6 -2
  528. data/spec/integration/cursor_reaping_spec.rb +1 -1
  529. data/spec/integration/docs_examples_spec.rb +2 -2
  530. data/spec/integration/error_detection_spec.rb +1 -1
  531. data/spec/integration/find_options_spec.rb +227 -0
  532. data/spec/integration/fork_reconnect_spec.rb +2 -2
  533. data/spec/integration/get_more_spec.rb +1 -1
  534. data/spec/integration/grid_fs_bucket_spec.rb +1 -1
  535. data/spec/integration/heartbeat_events_spec.rb +1 -1
  536. data/spec/integration/map_reduce_spec.rb +5 -1
  537. data/spec/integration/mmapv1_spec.rb +1 -1
  538. data/spec/integration/mongos_pinning_spec.rb +1 -1
  539. data/spec/integration/ocsp_connectivity_spec.rb +1 -1
  540. data/spec/integration/ocsp_verifier_cache_spec.rb +1 -1
  541. data/spec/integration/ocsp_verifier_spec.rb +2 -2
  542. data/spec/integration/operation_failure_code_spec.rb +1 -1
  543. data/spec/integration/operation_failure_message_spec.rb +1 -0
  544. data/spec/integration/query_cache_spec.rb +90 -3
  545. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  546. data/spec/integration/read_concern_spec.rb +1 -1
  547. data/spec/integration/read_preference_spec.rb +1 -1
  548. data/spec/integration/reconnect_spec.rb +4 -1
  549. data/spec/integration/retryable_errors_spec.rb +1 -1
  550. data/spec/integration/retryable_reads_errors_spec.rb +110 -0
  551. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  552. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  553. data/spec/integration/retryable_writes/shared/adds_diagnostics.rb +1 -1
  554. data/spec/integration/retryable_writes/shared/does_not_support_retries.rb +1 -1
  555. data/spec/integration/retryable_writes/shared/only_supports_legacy_retries.rb +1 -1
  556. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +1 -1
  557. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +1 -1
  558. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +1 -1
  559. data/spec/integration/retryable_writes/shared/supports_legacy_retries.rb +1 -1
  560. data/spec/integration/retryable_writes/shared/supports_modern_retries.rb +1 -1
  561. data/spec/integration/retryable_writes/shared/supports_retries.rb +1 -1
  562. data/spec/integration/retryable_writes_errors_spec.rb +160 -2
  563. data/spec/integration/sdam_error_handling_spec.rb +65 -4
  564. data/spec/integration/sdam_events_spec.rb +1 -1
  565. data/spec/integration/sdam_prose_spec.rb +3 -3
  566. data/spec/integration/search_indexes_prose_spec.rb +168 -0
  567. data/spec/integration/secondary_reads_spec.rb +1 -0
  568. data/spec/integration/server_description_spec.rb +1 -1
  569. data/spec/integration/server_monitor_spec.rb +1 -1
  570. data/spec/integration/server_selection_spec.rb +1 -1
  571. data/spec/integration/server_selector_spec.rb +5 -3
  572. data/spec/integration/server_spec.rb +23 -26
  573. data/spec/integration/shell_examples_spec.rb +1 -1
  574. data/spec/integration/size_limit_spec.rb +1 -1
  575. data/spec/integration/snappy_compression_spec.rb +1 -1
  576. data/spec/integration/snapshot_query_examples_spec.rb +9 -7
  577. data/spec/integration/srv_monitoring_spec.rb +2 -1
  578. data/spec/integration/srv_spec.rb +3 -3
  579. data/spec/integration/ssl_uri_options_spec.rb +1 -1
  580. data/spec/integration/step_down_spec.rb +5 -3
  581. data/spec/integration/time_zone_querying_spec.rb +1 -1
  582. data/spec/integration/transaction_pinning_spec.rb +18 -4
  583. data/spec/integration/transactions_api_examples_spec.rb +1 -1
  584. data/spec/integration/transactions_examples_spec.rb +1 -1
  585. data/spec/integration/truncated_utf8_spec.rb +1 -1
  586. data/spec/integration/versioned_api_examples_spec.rb +2 -2
  587. data/spec/integration/x509_auth_spec.rb +1 -1
  588. data/spec/integration/zlib_compression_spec.rb +1 -1
  589. data/spec/integration/zstd_compression_spec.rb +1 -1
  590. data/spec/kerberos/kerberos_spec.rb +1 -1
  591. data/spec/lite_spec_helper.rb +47 -12
  592. data/spec/mongo/address/ipv4_spec.rb +1 -1
  593. data/spec/mongo/address/ipv6_spec.rb +1 -1
  594. data/spec/mongo/address/unix_spec.rb +1 -1
  595. data/spec/mongo/address/validator_spec.rb +1 -1
  596. data/spec/mongo/address_spec.rb +8 -2
  597. data/spec/mongo/auth/aws/credential_cache_spec.rb +63 -0
  598. data/spec/mongo/auth/aws/credentials_retriever_spec.rb +90 -0
  599. data/spec/mongo/auth/aws/credentials_spec.rb +46 -0
  600. data/spec/mongo/auth/aws/request_region_spec.rb +1 -1
  601. data/spec/mongo/auth/aws/request_spec.rb +1 -1
  602. data/spec/mongo/auth/cr_spec.rb +2 -22
  603. data/spec/mongo/auth/gssapi/conversation_spec.rb +1 -1
  604. data/spec/mongo/auth/invalid_mechanism_spec.rb +1 -1
  605. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  606. data/spec/mongo/auth/ldap_spec.rb +1 -1
  607. data/spec/mongo/auth/scram/conversation_spec.rb +1 -1
  608. data/spec/mongo/auth/scram256/conversation_spec.rb +1 -1
  609. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -1
  610. data/spec/mongo/auth/scram_spec.rb +1 -1
  611. data/spec/mongo/auth/stringprep/profiles/sasl_spec.rb +1 -1
  612. data/spec/mongo/auth/stringprep_spec.rb +1 -1
  613. data/spec/mongo/auth/user/view_spec.rb +96 -1
  614. data/spec/mongo/auth/user_spec.rb +1 -1
  615. data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
  616. data/spec/mongo/auth/x509_spec.rb +1 -1
  617. data/spec/mongo/auth_spec.rb +1 -1
  618. data/spec/mongo/bson_spec.rb +1 -1
  619. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +1 -1
  620. data/spec/mongo/bulk_write/result_spec.rb +1 -1
  621. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +1 -1
  622. data/spec/mongo/bulk_write_spec.rb +1 -1
  623. data/spec/mongo/caching_cursor_spec.rb +1 -1
  624. data/spec/mongo/client_construction_spec.rb +619 -693
  625. data/spec/mongo/client_encryption_spec.rb +1 -1
  626. data/spec/mongo/client_spec.rb +172 -231
  627. data/spec/mongo/cluster/cursor_reaper_spec.rb +1 -1
  628. data/spec/mongo/cluster/periodic_executor_spec.rb +1 -1
  629. data/spec/mongo/cluster/socket_reaper_spec.rb +1 -1
  630. data/spec/mongo/cluster/topology/replica_set_spec.rb +1 -1
  631. data/spec/mongo/cluster/topology/sharded_spec.rb +1 -1
  632. data/spec/mongo/cluster/topology/single_spec.rb +1 -1
  633. data/spec/mongo/cluster/topology/unknown_spec.rb +1 -1
  634. data/spec/mongo/cluster/topology_spec.rb +1 -1
  635. data/spec/mongo/cluster_spec.rb +156 -154
  636. data/spec/mongo/cluster_time_spec.rb +1 -1
  637. data/spec/mongo/collection/view/aggregation_spec.rb +1 -1
  638. data/spec/mongo/collection/view/builder/find_command_spec.rb +1 -1
  639. data/spec/mongo/collection/view/builder/op_query_spec.rb +1 -1
  640. data/spec/mongo/collection/view/change_stream_resume_spec.rb +1 -1
  641. data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
  642. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  643. data/spec/mongo/collection/view/immutable_spec.rb +1 -1
  644. data/spec/mongo/collection/view/iterable_spec.rb +1 -1
  645. data/spec/mongo/collection/view/map_reduce_spec.rb +11 -1
  646. data/spec/mongo/collection/view/readable_spec.rb +139 -1
  647. data/spec/mongo/collection/view/writable_spec.rb +1 -1
  648. data/spec/mongo/collection/view_spec.rb +1 -1
  649. data/spec/mongo/collection_crud_spec.rb +1 -1
  650. data/spec/mongo/collection_ddl_spec.rb +116 -66
  651. data/spec/mongo/collection_spec.rb +11 -7
  652. data/spec/mongo/condition_variable_spec.rb +104 -0
  653. data/spec/mongo/config/options_spec.rb +1 -0
  654. data/spec/mongo/config_spec.rb +2 -1
  655. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  656. data/spec/mongo/crypt/auto_encrypter_spec.rb +8 -1
  657. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  658. data/spec/mongo/crypt/binary_spec.rb +1 -1
  659. data/spec/mongo/crypt/binding/binary_spec.rb +1 -1
  660. data/spec/mongo/crypt/binding/context_spec.rb +1 -1
  661. data/spec/mongo/crypt/binding/helpers_spec.rb +1 -1
  662. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +1 -1
  663. data/spec/mongo/crypt/binding/status_spec.rb +1 -1
  664. data/spec/mongo/crypt/binding/version_spec.rb +19 -5
  665. data/spec/mongo/crypt/binding_unloaded_spec.rb +1 -1
  666. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  667. data/spec/mongo/crypt/encryption_io_spec.rb +1 -1
  668. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  669. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +3 -3
  670. data/spec/mongo/crypt/handle_spec.rb +19 -4
  671. data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +1 -1
  672. data/spec/mongo/crypt/hooks_spec.rb +2 -2
  673. data/spec/mongo/crypt/kms/azure/credentials_retriever_spec.rb +86 -0
  674. data/spec/mongo/crypt/kms/credentials_spec.rb +17 -1
  675. data/spec/mongo/crypt/kms_spec.rb +1 -1
  676. data/spec/mongo/crypt/status_spec.rb +1 -1
  677. data/spec/mongo/crypt_spec.rb +21 -0
  678. data/spec/mongo/cursor/builder/get_more_command_spec.rb +1 -1
  679. data/spec/mongo/cursor/builder/op_get_more_spec.rb +1 -1
  680. data/spec/mongo/cursor_spec.rb +58 -11
  681. data/spec/mongo/database_spec.rb +1 -1
  682. data/spec/mongo/distinguishing_semaphore_spec.rb +7 -7
  683. data/spec/mongo/error/bulk_write_error_spec.rb +1 -1
  684. data/spec/mongo/error/crypt_error_spec.rb +1 -1
  685. data/spec/mongo/error/max_bson_size_spec.rb +1 -1
  686. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  687. data/spec/mongo/error/notable_spec.rb +1 -1
  688. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  689. data/spec/mongo/error/operation_failure_spec.rb +1 -1
  690. data/spec/mongo/error/parser_spec.rb +1 -1
  691. data/spec/mongo/error/unsupported_option_spec.rb +1 -1
  692. data/spec/mongo/event/publisher_spec.rb +1 -1
  693. data/spec/mongo/event/subscriber_spec.rb +1 -1
  694. data/spec/mongo/grid/file/chunk_spec.rb +1 -1
  695. data/spec/mongo/grid/file/info_spec.rb +1 -1
  696. data/spec/mongo/grid/file_spec.rb +1 -1
  697. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  698. data/spec/mongo/grid/stream/read_spec.rb +1 -1
  699. data/spec/mongo/grid/stream/write_spec.rb +1 -1
  700. data/spec/mongo/grid/stream_spec.rb +1 -1
  701. data/spec/mongo/id_spec.rb +2 -2
  702. data/spec/mongo/index/view_spec.rb +4 -4
  703. data/spec/mongo/lint_spec.rb +2 -2
  704. data/spec/mongo/logger_spec.rb +1 -1
  705. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +1 -1
  706. data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +2 -2
  707. data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +2 -2
  708. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +2 -2
  709. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +2 -2
  710. data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +2 -2
  711. data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +2 -2
  712. data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +2 -2
  713. data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +2 -2
  714. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +2 -2
  715. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +2 -2
  716. data/spec/mongo/monitoring/event/command_failed_spec.rb +1 -1
  717. data/spec/mongo/monitoring/event/command_started_spec.rb +1 -1
  718. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +1 -1
  719. data/spec/mongo/monitoring/event/secure_spec.rb +1 -1
  720. data/spec/mongo/monitoring/event/server_closed_spec.rb +1 -1
  721. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -1
  722. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +1 -1
  723. data/spec/mongo/monitoring/event/server_heartbeat_started_spec.rb +1 -1
  724. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +1 -1
  725. data/spec/mongo/monitoring/event/server_opening_spec.rb +1 -1
  726. data/spec/mongo/monitoring/event/topology_changed_spec.rb +1 -1
  727. data/spec/mongo/monitoring/event/topology_closed_spec.rb +1 -1
  728. data/spec/mongo/monitoring/event/topology_opening_spec.rb +1 -1
  729. data/spec/mongo/monitoring_spec.rb +1 -1
  730. data/spec/mongo/operation/aggregate/result_spec.rb +1 -1
  731. data/spec/mongo/operation/aggregate_spec.rb +1 -1
  732. data/spec/mongo/operation/collections_info_spec.rb +1 -1
  733. data/spec/mongo/operation/command_spec.rb +1 -1
  734. data/spec/mongo/operation/create/op_msg_spec.rb +1 -1
  735. data/spec/mongo/operation/create_index_spec.rb +1 -1
  736. data/spec/mongo/operation/create_user_spec.rb +1 -1
  737. data/spec/mongo/operation/delete/bulk_spec.rb +1 -1
  738. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  739. data/spec/mongo/operation/delete_spec.rb +1 -1
  740. data/spec/mongo/operation/drop_index_spec.rb +1 -1
  741. data/spec/mongo/operation/find/builder/flags_spec.rb +1 -1
  742. data/spec/mongo/operation/find/builder/modifiers_spec.rb +1 -1
  743. data/spec/mongo/operation/indexes_spec.rb +1 -1
  744. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  745. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  746. data/spec/mongo/operation/insert_spec.rb +1 -1
  747. data/spec/mongo/operation/limited_spec.rb +1 -1
  748. data/spec/mongo/operation/map_reduce_spec.rb +1 -1
  749. data/spec/mongo/operation/read_preference_legacy_spec.rb +1 -1
  750. data/spec/mongo/operation/read_preference_op_msg_spec.rb +1 -1
  751. data/spec/mongo/operation/remove_user_spec.rb +1 -1
  752. data/spec/mongo/operation/result_spec.rb +1 -1
  753. data/spec/mongo/operation/specifiable_spec.rb +1 -1
  754. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  755. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  756. data/spec/mongo/operation/update_spec.rb +1 -1
  757. data/spec/mongo/operation/update_user_spec.rb +1 -1
  758. data/spec/mongo/options/redacted_spec.rb +2 -2
  759. data/spec/mongo/protocol/caching_hash_spec.rb +1 -46
  760. data/spec/mongo/protocol/compressed_spec.rb +1 -1
  761. data/spec/mongo/protocol/get_more_spec.rb +1 -1
  762. data/spec/mongo/protocol/kill_cursors_spec.rb +1 -1
  763. data/spec/mongo/protocol/msg_spec.rb +4 -66
  764. data/spec/mongo/protocol/query_spec.rb +1 -1
  765. data/spec/mongo/protocol/registry_spec.rb +1 -1
  766. data/spec/mongo/protocol/reply_spec.rb +1 -1
  767. data/spec/mongo/query_cache_middleware_spec.rb +1 -1
  768. data/spec/mongo/query_cache_spec.rb +1 -1
  769. data/spec/mongo/retryable_spec.rb +5 -3
  770. data/spec/mongo/semaphore_spec.rb +7 -7
  771. data/spec/mongo/server/app_metadata/environment_spec.rb +209 -0
  772. data/spec/mongo/server/app_metadata/truncator_spec.rb +158 -0
  773. data/spec/mongo/server/app_metadata_spec.rb +44 -66
  774. data/spec/mongo/server/connection_auth_spec.rb +1 -1
  775. data/spec/mongo/server/connection_common_spec.rb +1 -1
  776. data/spec/mongo/server/connection_pool/populator_spec.rb +17 -3
  777. data/spec/mongo/server/connection_pool_spec.rb +447 -10
  778. data/spec/mongo/server/connection_spec.rb +17 -4
  779. data/spec/mongo/server/description/features_spec.rb +1 -1
  780. data/spec/mongo/server/description_query_methods_spec.rb +1 -1
  781. data/spec/mongo/server/description_spec.rb +1 -1
  782. data/spec/mongo/server/monitor/app_metadata_spec.rb +1 -1
  783. data/spec/mongo/server/monitor/connection_spec.rb +3 -3
  784. data/spec/mongo/server/monitor_spec.rb +6 -5
  785. data/spec/mongo/server/push_monitor_spec.rb +1 -1
  786. data/spec/mongo/server/round_trip_time_averager_spec.rb +1 -1
  787. data/spec/mongo/server_selector/nearest_spec.rb +1 -1
  788. data/spec/mongo/server_selector/primary_preferred_spec.rb +1 -1
  789. data/spec/mongo/server_selector/primary_spec.rb +1 -1
  790. data/spec/mongo/server_selector/secondary_preferred_spec.rb +1 -1
  791. data/spec/mongo/server_selector/secondary_spec.rb +1 -1
  792. data/spec/mongo/server_selector_spec.rb +1 -1
  793. data/spec/mongo/server_spec.rb +32 -5
  794. data/spec/mongo/session/server_session_spec.rb +1 -1
  795. data/spec/mongo/session/session_pool_spec.rb +1 -1
  796. data/spec/mongo/session_spec.rb +1 -1
  797. data/spec/mongo/session_transaction_spec.rb +2 -2
  798. data/spec/mongo/socket/ssl_spec.rb +3 -9
  799. data/spec/mongo/socket/tcp_spec.rb +1 -1
  800. data/spec/mongo/socket/unix_spec.rb +1 -1
  801. data/spec/mongo/socket_spec.rb +1 -1
  802. data/spec/mongo/srv/monitor_spec.rb +1 -1
  803. data/spec/mongo/srv/result_spec.rb +1 -1
  804. data/spec/mongo/timeout_spec.rb +1 -1
  805. data/spec/mongo/tls_context_hooks_spec.rb +1 -1
  806. data/spec/mongo/uri/options_mapper_spec.rb +1605 -0
  807. data/spec/mongo/uri/srv_protocol_spec.rb +162 -2
  808. data/spec/mongo/uri_option_parsing_spec.rb +1 -1
  809. data/spec/mongo/uri_spec.rb +143 -2
  810. data/spec/mongo/utils_spec.rb +1 -1
  811. data/spec/mongo/write_concern/acknowledged_spec.rb +1 -1
  812. data/spec/mongo/write_concern/unacknowledged_spec.rb +1 -1
  813. data/spec/mongo/write_concern_spec.rb +1 -1
  814. data/spec/runners/auth.rb +1 -1
  815. data/spec/runners/change_streams/outcome.rb +1 -1
  816. data/spec/runners/change_streams/spec.rb +1 -1
  817. data/spec/runners/change_streams/test.rb +1 -1
  818. data/spec/runners/cmap/verifier.rb +2 -2
  819. data/spec/runners/cmap.rb +188 -45
  820. data/spec/runners/command_monitoring.rb +1 -1
  821. data/spec/runners/connection_string.rb +1 -1
  822. data/spec/runners/crud/context.rb +1 -1
  823. data/spec/runners/crud/operation.rb +2 -2
  824. data/spec/runners/crud/outcome.rb +1 -1
  825. data/spec/runners/crud/requirement.rb +3 -3
  826. data/spec/runners/crud/spec.rb +2 -2
  827. data/spec/runners/crud/test.rb +1 -1
  828. data/spec/runners/crud/test_base.rb +2 -2
  829. data/spec/runners/crud/verifier.rb +3 -3
  830. data/spec/runners/crud.rb +1 -1
  831. data/spec/runners/gridfs.rb +1 -1
  832. data/spec/runners/read_write_concern_document.rb +1 -1
  833. data/spec/runners/sdam/verifier.rb +1 -1
  834. data/spec/runners/sdam.rb +1 -1
  835. data/spec/runners/server_selection.rb +1 -1
  836. data/spec/runners/server_selection_rtt.rb +1 -1
  837. data/spec/runners/transactions/operation.rb +15 -9
  838. data/spec/runners/transactions/spec.rb +1 -1
  839. data/spec/runners/transactions/test.rb +44 -3
  840. data/spec/runners/transactions.rb +1 -1
  841. data/spec/runners/unified/assertions.rb +94 -77
  842. data/spec/runners/unified/change_stream_operations.rb +14 -3
  843. data/spec/runners/unified/client_side_encryption_operations.rb +1 -1
  844. data/spec/runners/unified/crud_operations.rb +11 -2
  845. data/spec/runners/unified/ddl_operations.rb +80 -4
  846. data/spec/runners/unified/entity_map.rb +1 -1
  847. data/spec/runners/unified/error.rb +1 -1
  848. data/spec/runners/unified/event_subscriber.rb +9 -3
  849. data/spec/runners/unified/exceptions.rb +1 -1
  850. data/spec/runners/unified/grid_fs_operations.rb +1 -1
  851. data/spec/runners/unified/search_index_operations.rb +63 -0
  852. data/spec/runners/unified/support_operations.rb +66 -2
  853. data/spec/runners/unified/test.rb +101 -25
  854. data/spec/runners/unified/test_group.rb +1 -1
  855. data/spec/runners/unified/thread_operations.rb +73 -0
  856. data/spec/runners/unified.rb +9 -6
  857. data/spec/shared/lib/mrss/docker_runner.rb +4 -0
  858. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  859. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  860. data/spec/shared/lib/mrss/utils.rb +28 -6
  861. data/spec/shared/share/Dockerfile.erb +24 -19
  862. data/spec/shared/shlib/server.sh +32 -8
  863. data/spec/shared/shlib/set_env.sh +4 -4
  864. data/spec/solo/clean_exit_spec.rb +4 -11
  865. data/spec/spec_helper.rb +2 -2
  866. data/spec/spec_tests/auth_spec.rb +1 -1
  867. data/spec/spec_tests/change_streams_unified_spec.rb +2 -1
  868. data/spec/spec_tests/client_side_encryption_spec.rb +25 -2
  869. data/spec/spec_tests/client_side_encryption_unified_spec.rb +12 -2
  870. data/spec/spec_tests/cmap_spec.rb +29 -15
  871. data/spec/spec_tests/collection_management_spec.rb +1 -1
  872. data/spec/spec_tests/command_monitoring_unified_spec.rb +1 -1
  873. data/spec/spec_tests/connection_string_spec.rb +1 -1
  874. data/spec/spec_tests/crud_spec.rb +1 -1
  875. data/spec/spec_tests/crud_unified_spec.rb +1 -1
  876. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +41 -0
  877. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +103 -0
  878. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +2 -6
  879. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  880. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -3
  881. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -3
  882. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +15 -6
  883. data/spec/spec_tests/data/client_side_encryption/awsTemporary.yml +57 -0
  884. data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +5 -4
  885. data/spec/spec_tests/data/client_side_encryption/{fle2-BypassQueryAnalysis.yml → fle2v2-BypassQueryAnalysis.yml} +18 -30
  886. data/spec/spec_tests/data/client_side_encryption/{fle2-Compact.yml → fle2v2-Compact.yml} +5 -3
  887. data/spec/spec_tests/data/client_side_encryption/fle2v2-CreateCollection-OldServer.yml +61 -0
  888. data/spec/spec_tests/data/client_side_encryption/{fle2-CreateCollection.yml → fle2v2-CreateCollection.yml} +212 -538
  889. data/spec/spec_tests/data/client_side_encryption/{fle2-DecryptExistingData.yml → fle2v2-DecryptExistingData.yml} +4 -2
  890. data/spec/spec_tests/data/client_side_encryption/{fle2-Delete.yml → fle2v2-Delete.yml} +17 -24
  891. data/spec/spec_tests/data/client_side_encryption/{fle2-EncryptedFields-vs-EncryptedFieldsMap.yml → fle2v2-EncryptedFields-vs-EncryptedFieldsMap.yml} +5 -6
  892. data/spec/spec_tests/data/client_side_encryption/{fle2-EncryptedFields-vs-jsonSchema.yml → fle2v2-EncryptedFields-vs-jsonSchema.yml} +18 -6
  893. data/spec/spec_tests/data/client_side_encryption/{fle2-EncryptedFieldsMap-defaults.yml → fle2v2-EncryptedFieldsMap-defaults.yml} +6 -5
  894. data/spec/spec_tests/data/client_side_encryption/{fle2-FindOneAndUpdate.yml → fle2v2-FindOneAndUpdate.yml} +31 -44
  895. data/spec/spec_tests/data/client_side_encryption/{fle2-InsertFind-Indexed.yml → fle2v2-InsertFind-Indexed.yml} +16 -6
  896. data/spec/spec_tests/data/client_side_encryption/{fle2-InsertFind-Unindexed.yml → fle2v2-InsertFind-Unindexed.yml} +10 -4
  897. data/spec/spec_tests/data/client_side_encryption/{fle2-MissingKey.yml → fle2v2-MissingKey.yml} +5 -3
  898. data/spec/spec_tests/data/client_side_encryption/{fle2-NoEncryption.yml → fle2v2-NoEncryption.yml} +4 -2
  899. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +241 -0
  900. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +422 -0
  901. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +182 -0
  902. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +239 -0
  903. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +235 -0
  904. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +252 -0
  905. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +1687 -0
  906. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +293 -0
  907. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +905 -0
  908. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +1684 -0
  909. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +1680 -0
  910. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +1697 -0
  911. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +329 -0
  912. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +424 -0
  913. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +226 -0
  914. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +327 -0
  915. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +319 -0
  916. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +336 -0
  917. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +913 -0
  918. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +292 -0
  919. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +518 -0
  920. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +911 -0
  921. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +907 -0
  922. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +924 -0
  923. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +325 -0
  924. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +424 -0
  925. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +224 -0
  926. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +323 -0
  927. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +319 -0
  928. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +338 -0
  929. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +241 -0
  930. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +423 -0
  931. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +182 -0
  932. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +239 -0
  933. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +235 -0
  934. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +254 -0
  935. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +241 -0
  936. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +422 -0
  937. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +182 -0
  938. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +239 -0
  939. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +235 -0
  940. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +254 -0
  941. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +43 -0
  942. data/spec/spec_tests/data/client_side_encryption/{fle2-Update.yml → fle2v2-Update.yml} +33 -44
  943. data/spec/spec_tests/data/client_side_encryption/{fle2-validatorAndPartialFieldExpression.yml → fle2v2-validatorAndPartialFieldExpression.yml} +10 -9
  944. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +1 -1
  945. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +1 -1
  946. data/spec/spec_tests/data/cmap/connection-must-have-id.yml +2 -0
  947. data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +2 -0
  948. data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +2 -0
  949. data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +2 -0
  950. data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +3 -1
  951. data/spec/spec_tests/data/cmap/pool-checkin.yml +5 -0
  952. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +2 -0
  953. data/spec/spec_tests/data/cmap/pool-checkout-custom-maxConnecting-is-enforced.yml +50 -0
  954. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +2 -0
  955. data/spec/spec_tests/data/cmap/pool-checkout-maxConnecting-is-enforced.yml +81 -0
  956. data/spec/spec_tests/data/cmap/pool-checkout-maxConnecting-timeout.yml +71 -0
  957. data/spec/spec_tests/data/cmap/pool-checkout-minPoolSize-connection-maxConnecting.yml +64 -0
  958. data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +2 -0
  959. data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +6 -0
  960. data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +8 -0
  961. data/spec/spec_tests/data/cmap/pool-checkout-returned-connection-maxConnecting.yml +88 -0
  962. data/spec/spec_tests/data/cmap/pool-clear-interrupt-immediately.yml +49 -0
  963. data/spec/spec_tests/data/cmap/pool-clear-interrupting-pending-connections.yml +43 -0
  964. data/spec/spec_tests/data/cmap/pool-clear-min-size.yml +41 -0
  965. data/spec/spec_tests/data/cmap/pool-clear-paused.yml +18 -0
  966. data/spec/spec_tests/data/cmap/pool-clear-ready.yml +39 -0
  967. data/spec/spec_tests/data/cmap/pool-clear-schedule-run-interruptInUseConnections-false.yml +48 -0
  968. data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +2 -0
  969. data/spec/spec_tests/data/cmap/pool-create-max-size.yml +2 -0
  970. data/spec/spec_tests/data/cmap/pool-create-min-size-error.yml +43 -0
  971. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +9 -0
  972. data/spec/spec_tests/data/cmap/pool-ready-ready.yml +22 -0
  973. data/spec/spec_tests/data/cmap/pool-ready.yml +30 -0
  974. data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +2 -0
  975. data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +6 -1
  976. data/spec/spec_tests/data/collection_management/modifyCollection-errorResponse.yml +59 -0
  977. data/spec/spec_tests/data/collection_management/timeseries-collection.yml +35 -0
  978. data/spec/spec_tests/data/command_monitoring_unified/redacted-commands.yml +8 -0
  979. data/spec/spec_tests/data/command_monitoring_unified/writeConcernError.yml +80 -0
  980. data/spec/spec_tests/data/crud_unified/aggregate-merge-errorResponse.yml +42 -0
  981. data/spec/spec_tests/data/crud_unified/bulkWrite-errorResponse.yml +50 -0
  982. data/spec/spec_tests/data/crud_unified/deleteOne-errorResponse.yml +46 -0
  983. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +44 -0
  984. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-errorResponse.yml +69 -0
  985. data/spec/spec_tests/data/crud_unified/insertOne-errorResponse.yml +46 -0
  986. data/spec/spec_tests/data/crud_unified/updateOne-errorResponse.yml +47 -0
  987. data/spec/spec_tests/data/index_management/createSearchIndex.yml +62 -0
  988. data/spec/spec_tests/data/index_management/createSearchIndexes.yml +83 -0
  989. data/spec/spec_tests/data/index_management/dropSearchIndex.yml +42 -0
  990. data/spec/spec_tests/data/index_management/listSearchIndexes.yml +85 -0
  991. data/spec/spec_tests/data/index_management/updateSearchIndex.yml +45 -0
  992. data/spec/spec_tests/data/retryable_reads/unified/handshakeError.yml +1266 -53
  993. data/spec/spec_tests/data/retryable_writes/unified/bulkWrite-serverErrors.yml +1 -1
  994. data/spec/spec_tests/data/retryable_writes/unified/handshakeError.yml +706 -58
  995. data/spec/spec_tests/data/retryable_writes/unified/insertOne-noWritesPerformedError.yml +54 -0
  996. data/spec/spec_tests/data/retryable_writes/unified/insertOne-serverErrors.yml +1 -1
  997. data/spec/spec_tests/data/sdam/rs/electionId_precedence_setVersion.yml +62 -0
  998. data/spec/spec_tests/data/sdam/rs/null_election_id-pre-6.0.yml +175 -0
  999. data/spec/spec_tests/data/sdam/rs/null_election_id.yml +20 -18
  1000. data/spec/spec_tests/data/sdam/rs/secondary_ignore_ok_0-pre-6.0.yml +87 -0
  1001. data/spec/spec_tests/data/sdam/rs/secondary_ignore_ok_0.yml +1 -1
  1002. data/spec/spec_tests/data/sdam/rs/set_version_can_rollback.yml +101 -0
  1003. data/spec/spec_tests/data/sdam/rs/setversion_equal_max_without_electionid.yml +78 -0
  1004. data/spec/spec_tests/data/sdam/rs/setversion_greaterthan_max_without_electionid.yml +79 -0
  1005. data/spec/spec_tests/data/sdam/rs/setversion_without_electionid-pre-6.0.yml +79 -0
  1006. data/spec/spec_tests/data/sdam/rs/setversion_without_electionid.yml +9 -10
  1007. data/spec/spec_tests/data/sdam/rs/use_setversion_without_electionid-pre-6.0.yml +117 -0
  1008. data/spec/spec_tests/data/sdam/rs/use_setversion_without_electionid.yml +23 -21
  1009. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -1
  1010. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_no_primary.yml +38 -39
  1011. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary.yml +38 -39
  1012. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +1 -1
  1013. data/spec/spec_tests/data/sdam_monitoring/required_replica_set.yml +1 -1
  1014. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +1 -1
  1015. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  1016. data/spec/spec_tests/data/sdam_unified/auth-error.yml +130 -0
  1017. data/spec/spec_tests/data/sdam_unified/auth-misc-command-error.yml +132 -0
  1018. data/spec/spec_tests/data/sdam_unified/auth-network-error.yml +132 -0
  1019. data/spec/spec_tests/data/sdam_unified/auth-network-timeout-error.yml +138 -0
  1020. data/spec/spec_tests/data/sdam_unified/auth-shutdown-error.yml +133 -0
  1021. data/spec/spec_tests/data/sdam_unified/cancel-server-check.yml +143 -0
  1022. data/spec/spec_tests/data/sdam_unified/connectTimeoutMS.yml +130 -0
  1023. data/spec/spec_tests/data/sdam_unified/find-network-error.yml +135 -0
  1024. data/spec/spec_tests/data/sdam_unified/find-network-timeout-error.yml +119 -0
  1025. data/spec/spec_tests/data/sdam_unified/find-shutdown-error.yml +163 -0
  1026. data/spec/spec_tests/data/sdam_unified/hello-command-error.yml +233 -0
  1027. data/spec/spec_tests/data/sdam_unified/hello-network-error.yml +228 -0
  1028. data/spec/spec_tests/data/sdam_unified/hello-timeout.yml +318 -0
  1029. data/spec/spec_tests/data/sdam_unified/insert-network-error.yml +137 -0
  1030. data/spec/spec_tests/data/sdam_unified/insert-shutdown-error.yml +162 -0
  1031. data/spec/spec_tests/data/sdam_unified/interruptInUse-pool-clear.yml +340 -0
  1032. data/spec/spec_tests/data/sdam_unified/minPoolSize-error.yml +125 -0
  1033. data/spec/spec_tests/data/sdam_unified/pool-cleared-error.yml +239 -0
  1034. data/spec/spec_tests/data/sdam_unified/rediscover-quickly-after-step-down.yml +144 -0
  1035. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +6 -5
  1036. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +2 -2
  1037. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +5 -4
  1038. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-conflicts_with_loadBalanced-true-txt.yml +1 -1
  1039. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-zero-txt.yml +4 -3
  1040. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-zero.yml +4 -3
  1041. data/spec/spec_tests/data/sessions_unified/implicit-sessions-default-causal-consistency.yml +119 -0
  1042. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +1 -1
  1043. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +1 -1
  1044. data/spec/spec_tests/data/transactions_unified/mongos-unpin.yml +1 -1
  1045. data/spec/spec_tests/data/unified/valid-fail/entity-findCursor-malformed.yml +31 -0
  1046. data/spec/spec_tests/data/unified/valid-fail/entity-findCursor.yml +31 -0
  1047. data/spec/spec_tests/data/unified/valid-fail/ignoreResultAndError-malformed.yml +34 -0
  1048. data/spec/spec_tests/data/unified/valid-fail/ignoreResultAndError.yml +35 -0
  1049. data/spec/spec_tests/data/unified/valid-pass/assertNumberConnectionsCheckedOut.yml +17 -0
  1050. data/spec/spec_tests/data/unified/valid-pass/collectionData-createOptions.yml +37 -0
  1051. data/spec/spec_tests/data/unified/valid-pass/entity-client-cmap-events.yml +40 -0
  1052. data/spec/spec_tests/data/unified/valid-pass/entity-client-storeEventsAsEntities.yml +37 -0
  1053. data/spec/spec_tests/data/unified/valid-pass/expectedError-errorResponse.yml +39 -0
  1054. data/spec/spec_tests/data/unified/valid-pass/expectedEventsForClient-eventType.yml +66 -0
  1055. data/spec/spec_tests/data/unified/valid-pass/ignoreResultAndError.yml +34 -0
  1056. data/spec/spec_tests/data/unified/valid-pass/observeSensitiveCommands.yml +255 -0
  1057. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +18 -0
  1058. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +18 -12
  1059. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +3 -3
  1060. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +2 -2
  1061. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +1 -1
  1062. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +1 -1
  1063. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +4 -4
  1064. data/spec/spec_tests/gridfs_spec.rb +1 -1
  1065. data/spec/spec_tests/gridfs_unified_spec.rb +1 -1
  1066. data/spec/spec_tests/index_management_unified_spec.rb +13 -0
  1067. data/spec/spec_tests/load_balancers_spec.rb +1 -1
  1068. data/spec/spec_tests/max_staleness_spec.rb +1 -1
  1069. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +1 -1
  1070. data/spec/spec_tests/read_write_concern_document_spec.rb +1 -1
  1071. data/spec/spec_tests/read_write_concern_operaton_spec.rb +1 -1
  1072. data/spec/spec_tests/retryable_reads_spec.rb +3 -1
  1073. data/spec/spec_tests/retryable_reads_unified_spec.rb +1 -1
  1074. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  1075. data/spec/spec_tests/retryable_writes_unified_spec.rb +1 -1
  1076. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -1
  1077. data/spec/spec_tests/sdam_spec.rb +5 -1
  1078. data/spec/spec_tests/sdam_unified_spec.rb +13 -0
  1079. data/spec/spec_tests/seed_list_discovery_spec.rb +1 -1
  1080. data/spec/spec_tests/server_selection_rtt_spec.rb +1 -1
  1081. data/spec/spec_tests/server_selection_spec.rb +1 -1
  1082. data/spec/spec_tests/sessions_unified_spec.rb +1 -1
  1083. data/spec/spec_tests/transactions_api_spec.rb +1 -1
  1084. data/spec/spec_tests/transactions_spec.rb +1 -1
  1085. data/spec/spec_tests/transactions_unified_spec.rb +1 -1
  1086. data/spec/spec_tests/unified_spec.rb +1 -6
  1087. data/spec/spec_tests/uri_options_spec.rb +1 -1
  1088. data/spec/spec_tests/versioned_api_spec.rb +1 -1
  1089. data/spec/stress/cleanup_spec.rb +1 -1
  1090. data/spec/stress/connection_pool_stress_spec.rb +1 -62
  1091. data/spec/stress/connection_pool_timing_spec.rb +9 -34
  1092. data/spec/stress/fork_reconnect_stress_spec.rb +7 -8
  1093. data/spec/stress/push_monitor_close_spec.rb +1 -1
  1094. data/spec/support/authorization.rb +1 -1
  1095. data/spec/support/aws_utils/base.rb +1 -1
  1096. data/spec/support/aws_utils/inspector.rb +1 -1
  1097. data/spec/support/aws_utils/orchestrator.rb +20 -8
  1098. data/spec/support/aws_utils/provisioner.rb +1 -1
  1099. data/spec/support/aws_utils.rb +4 -3
  1100. data/spec/support/background_thread_registry.rb +1 -1
  1101. data/spec/support/certificates/atlas-ocsp-ca.crt +67 -67
  1102. data/spec/support/certificates/atlas-ocsp.crt +103 -103
  1103. data/spec/support/certificates/retrieve-atlas-cert +2 -0
  1104. data/spec/support/client_registry.rb +6 -2
  1105. data/spec/support/client_registry_macros.rb +1 -1
  1106. data/spec/support/cluster_tools.rb +13 -8
  1107. data/spec/support/common_shortcuts.rb +30 -5
  1108. data/spec/support/constraints.rb +15 -1
  1109. data/spec/support/crypt/{encryptedFields.json → encrypted_fields/encryptedFields.json} +0 -1
  1110. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +30 -0
  1111. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +21 -0
  1112. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +29 -0
  1113. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +21 -0
  1114. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +30 -0
  1115. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +27 -0
  1116. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +27 -0
  1117. data/spec/support/crypt.rb +13 -3
  1118. data/spec/support/dns.rb +1 -1
  1119. data/spec/support/faas/app/aws_lambda/mongodb/Gemfile.lock +19 -0
  1120. data/spec/support/json_ext_formatter.rb +1 -1
  1121. data/spec/support/keyword_struct.rb +1 -1
  1122. data/spec/support/local_resource_registry.rb +1 -1
  1123. data/spec/support/macros.rb +1 -0
  1124. data/spec/support/matchers.rb +5 -5
  1125. data/spec/support/mongos_macros.rb +7 -0
  1126. data/spec/support/monitoring_ext.rb +1 -1
  1127. data/spec/support/primary_socket.rb +1 -1
  1128. data/spec/support/sdam_formatter_integration.rb +1 -1
  1129. data/spec/support/shared/app_metadata.rb +15 -3
  1130. data/spec/support/shared/auth_context.rb +1 -0
  1131. data/spec/support/shared/protocol.rb +1 -1
  1132. data/spec/support/shared/scram_conversation.rb +1 -1
  1133. data/spec/support/shared/server_selector.rb +1 -1
  1134. data/spec/support/shared/session.rb +1 -1
  1135. data/spec/support/spec_config.rb +45 -3
  1136. data/spec/support/spec_setup.rb +1 -1
  1137. data/spec/support/using_hash.rb +11 -2
  1138. data/spec/support/utils.rb +277 -249
  1139. data.tar.gz.sig +0 -0
  1140. metadata +1504 -1191
  1141. metadata.gz.sig +0 -0
  1142. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +0 -96
  1143. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +0 -88
  1144. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +0 -85
  1145. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +0 -118
  1146. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +0 -152
  1147. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +0 -148
  1148. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +0 -219
  1149. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +0 -88
  1150. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +0 -117
  1151. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +0 -98
  1152. data/spec/spec_tests/data/unified/invalid/expectedEventsForClient-ignoreExtraEvents-type.yml +0 -15
  1153. data/spec/spec_tests/sdam_integration_spec.rb +0 -16
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # encoding: utf-8
2
+ # rubocop:todo all
3
3
 
4
4
  # Copyright (C) 2014-2020 MongoDB Inc.
5
5
  #
@@ -29,12 +29,16 @@ module Mongo
29
29
  # The default max size for the connection pool.
30
30
  #
31
31
  # @since 2.9.0
32
- DEFAULT_MAX_SIZE = 20.freeze
32
+ DEFAULT_MAX_SIZE = 20
33
33
 
34
34
  # The default min size for the connection pool.
35
35
  #
36
36
  # @since 2.9.0
37
- DEFAULT_MIN_SIZE = 0.freeze
37
+ DEFAULT_MIN_SIZE = 0
38
+
39
+ # The default maximum number of connections that can be connecting at
40
+ # any given time.
41
+ DEFAULT_MAX_CONNECTING = 2
38
42
 
39
43
  # The default timeout, in seconds, to wait for a connection.
40
44
  #
@@ -61,6 +65,11 @@ module Mongo
61
65
  #
62
66
  # @option options [ Integer ] :max_size The maximum pool size. Setting
63
67
  # this option to zero creates an unlimited connection pool.
68
+ # @option options [ Integer ] :max_connecting The maximum number of
69
+ # connections that can be connecting simultaneously. The default is 2.
70
+ # This option should be increased if there are many threads that share
71
+ # same connection pool and the application is experiencing timeouts
72
+ # while waiting for connections to be established.
64
73
  # @option options [ Integer ] :max_pool_size Deprecated.
65
74
  # The maximum pool size. If max_size is also given, max_size and
66
75
  # max_pool_size must be identical.
@@ -75,11 +84,21 @@ module Mongo
75
84
  # are given, their values must be identical.
76
85
  # @option options [ Float ] :max_idle_time The time, in seconds,
77
86
  # after which idle connections should be closed by the pool.
87
+ # @option options [ true, false ] :populator_io For internal driver
88
+ # use only. Set to false to prevent the populator threads from being
89
+ # created and started in the server's connection pool. It is intended
90
+ # for use in tests that also turn off monitoring_io, unless the populator
91
+ # is explicitly needed. If monitoring_io is off, but the populator_io
92
+ # is on, the populator needs to be manually closed at the end of the
93
+ # test, since a cluster without monitoring is considered not connected,
94
+ # and thus will not clean up the connection pool populator threads on
95
+ # close.
78
96
  # Note: Additionally, options for connections created by this pool should
79
97
  # be included in the options passed here, and they will be forwarded to
80
98
  # any connections created by the pool.
81
99
  #
82
100
  # @since 2.0.0, API changed in 2.9.0
101
+
83
102
  def initialize(server, options = {})
84
103
  unless server.is_a?(Server)
85
104
  raise ArgumentError, 'First argument must be a Server instance'
@@ -112,6 +131,7 @@ module Mongo
112
131
  @options = options.freeze
113
132
 
114
133
  @generation_manager = GenerationManager.new(server: server)
134
+ @ready = false
115
135
  @closed = false
116
136
 
117
137
  # A connection owned by this pool should be either in the
@@ -120,6 +140,7 @@ module Mongo
120
140
  @available_connections = available_connections = []
121
141
  @checked_out_connections = Set.new
122
142
  @pending_connections = Set.new
143
+ @interrupt_connections = []
123
144
 
124
145
  # Mutex used for synchronizing access to @available_connections and
125
146
  # @checked_out_connections. The pool object is thread-safe, thus
@@ -127,30 +148,42 @@ module Mongo
127
148
  # must do so under this lock.
128
149
  @lock = Mutex.new
129
150
 
130
- # Condition variable broadcast when a connection is added to
131
- # @available_connections, to wake up any threads waiting for an
132
- # available connection when pool is at max size
133
- @available_semaphore = Semaphore.new
134
-
135
151
  # Background thread reponsible for maintaining the size of
136
152
  # the pool to at least min_size
137
153
  @populator = Populator.new(self, options)
138
154
  @populate_semaphore = Semaphore.new
139
155
 
156
+ # Condition variable to enforce the first check in check_out: max_pool_size.
157
+ # This condition variable should be signaled when the number of
158
+ # unavailable connections decreases (pending + pending_connections +
159
+ # checked_out_connections).
160
+ @size_cv = Mongo::ConditionVariable.new(@lock)
161
+ # This represents the number of threads that have made it past the size_cv
162
+ # gate but have not acquired a connection to add to the pending_connections
163
+ # set.
164
+ @connection_requests = 0
165
+
166
+ # Condition variable to enforce the second check in check_out: max_connecting.
167
+ # Thei condition variable should be signaled when the number of pending
168
+ # connections decreases.
169
+ @max_connecting_cv = Mongo::ConditionVariable.new(@lock)
170
+ @max_connecting = options.fetch(:max_connecting, DEFAULT_MAX_CONNECTING)
171
+
140
172
  ObjectSpace.define_finalizer(self, self.class.finalize(@available_connections, @pending_connections, @populator))
141
173
 
142
174
  publish_cmap_event(
143
175
  Monitoring::Event::Cmap::PoolCreated.new(@server.address, options, self)
144
176
  )
145
-
146
- @populator.run! if min_size > 0
147
177
  end
148
178
 
149
179
  # @return [ Hash ] options The pool options.
150
180
  attr_reader :options
151
181
 
152
182
  # @api private
153
- def_delegators :@server, :address
183
+ attr_reader :server
184
+
185
+ # @api private
186
+ def_delegators :server, :address
154
187
 
155
188
  # Get the maximum size of the connection pool.
156
189
  #
@@ -196,7 +229,20 @@ module Mongo
196
229
  # being used by the queue.
197
230
  #
198
231
  # @api private
199
- def_delegator :generation_manager, :generation
232
+ def_delegators :generation_manager, :generation, :generation_unlocked
233
+
234
+ # A connection pool is paused if it is not closed and it is not ready.
235
+ #
236
+ # @return [ true | false ] whether the connection pool is paused.
237
+ #
238
+ # @raise [ Error::PoolClosedError ] If the pool has been closed.
239
+ def paused?
240
+ raise_if_closed!
241
+
242
+ @lock.synchronize do
243
+ !@ready
244
+ end
245
+ end
200
246
 
201
247
  # Size of the connection pool.
202
248
  #
@@ -222,6 +268,14 @@ module Mongo
222
268
  end
223
269
  private :unsynchronized_size
224
270
 
271
+ # @return [ Integer ] The number of unavailable connections in the pool.
272
+ # Used to calculate whether we have hit max_pool_size.
273
+ #
274
+ # @api private
275
+ def unavailable_connections
276
+ @checked_out_connections.length + @pending_connections.length + @connection_requests
277
+ end
278
+
225
279
  # Number of available connections in the pool.
226
280
  #
227
281
  # @return [ Integer ] Number of available connections.
@@ -244,14 +298,30 @@ module Mongo
244
298
  !!@closed
245
299
  end
246
300
 
301
+ # Whether the pool is ready.
302
+ #
303
+ # @return [ true | false ] Whether the pool is ready.
304
+ def ready?
305
+ @lock.synchronize do
306
+ @ready
307
+ end
308
+ end
309
+
247
310
  # @note This method is experimental and subject to change.
248
311
  #
249
312
  # @api experimental
250
313
  # @since 2.11.0
251
314
  def summary
252
315
  @lock.synchronize do
316
+ state = if closed?
317
+ 'closed'
318
+ elsif !@ready
319
+ 'paused'
320
+ else
321
+ 'ready'
322
+ end
253
323
  "#<ConnectionPool size=#{unsynchronized_size} (#{min_size}-#{max_size}) " +
254
- "used=#{@checked_out_connections.length} avail=#{@available_connections.length} pending=#{@pending_connections.length}>"
324
+ "used=#{@checked_out_connections.length} avail=#{@available_connections.length} pending=#{@pending_connections.length} #{state}>"
255
325
  end
256
326
  end
257
327
 
@@ -261,6 +331,9 @@ module Mongo
261
331
  # @api private
262
332
  attr_reader :populator
263
333
 
334
+ # @api private
335
+ attr_reader :max_connecting
336
+
264
337
  # Checks a connection out of the pool.
265
338
  #
266
339
  # If there are active connections in the pool, the most recently used
@@ -286,157 +359,10 @@ module Mongo
286
359
  Monitoring::Event::Cmap::ConnectionCheckOutStarted.new(@server.address)
287
360
  )
288
361
 
289
- if closed?
290
- publish_cmap_event(
291
- Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
292
- @server.address,
293
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::POOL_CLOSED
294
- ),
295
- )
296
- raise Error::PoolClosedError.new(@server.address, self)
297
- end
298
-
299
- deadline = Utils.monotonic_time + wait_timeout
300
- pid = Process.pid
301
- connection = nil
302
- # It seems that synchronize sets up its own loop, thus a simple break
303
- # is insufficient to break the outer loop
304
- catch(:done) do
305
- loop do
306
- # Lock must be taken on each iteration, rather for the method
307
- # overall, otherwise other threads will not be able to check in
308
- # a connection while this thread is waiting for one.
309
- @lock.synchronize do
310
- until @available_connections.empty?
311
- connection = next_available_connection(
312
- connection_global_id: connection_global_id
313
- )
314
-
315
- if connection.nil?
316
- if connection_global_id
317
- # A particular connection is requested, but it is not available.
318
- # If it is nether available not checked out, we should stop here.
319
- @checked_out_connections.detect do |conn|
320
- conn.connection_global_id == connection_global_id
321
- end.tap do |conn|
322
- if conn.nil?
323
- publish_cmap_event(
324
- Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
325
- @server.address,
326
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
327
- ),
328
- )
329
- raise Error::MissingConnection.new
330
- end
331
- end
332
- else
333
- break
334
- end
335
- end
336
-
337
- if connection.pid != pid
338
- log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{connection.pid}, new pid #{pid}")
339
- connection.disconnect!(reason: :stale)
340
- @populate_semaphore.signal
341
- next
342
- end
343
-
344
- if !connection.pinned?
345
- # If connection is marked as pinned, it is used by a transaction
346
- # or a series of cursor operations in a load balanced setup.
347
- # In this case connection should not be disconnected until
348
- # unpinned.
349
- if connection.generation != generation(
350
- service_id: connection.service_id
351
- )
352
- # Stale connections should be disconnected in the clear
353
- # method, but if any don't, check again here
354
- connection.disconnect!(reason: :stale)
355
- @populate_semaphore.signal
356
- next
357
- end
358
-
359
- if max_idle_time && connection.last_checkin &&
360
- Time.now - connection.last_checkin > max_idle_time
361
- then
362
- connection.disconnect!(reason: :idle)
363
- @populate_semaphore.signal
364
- next
365
- end
366
- end
367
-
368
- @pending_connections << connection
369
- throw(:done)
370
- end
362
+ raise_if_pool_closed!
363
+ raise_if_pool_paused_locked!
371
364
 
372
- if @server.load_balancer? && connection_global_id
373
- # We need a particular connection, and if it is not available
374
- # we can wait for an in-progress operation to return
375
- # such a connection to the pool.
376
- else
377
- # If we are below pool capacity, create a new connection.
378
- #
379
- # Ruby does not allow a thread to lock a mutex which it already
380
- # holds.
381
- if max_size == 0 || unsynchronized_size < max_size
382
- connection = create_connection
383
- @pending_connections << connection
384
- throw(:done)
385
- end
386
- end
387
- end
388
-
389
- wait = deadline - Utils.monotonic_time
390
- if wait <= 0
391
- publish_cmap_event(
392
- Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
393
- @server.address,
394
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::TIMEOUT,
395
- ),
396
- )
397
-
398
- msg = @lock.synchronize do
399
- connection_global_id_msg = if connection_global_id
400
- " for connection #{connection_global_id}"
401
- else
402
- ''
403
- end
404
-
405
- "Timed out attempting to check out a connection " +
406
- "from pool for #{@server.address}#{connection_global_id_msg} after #{wait_timeout} sec. " +
407
- "Connections in pool: #{@available_connections.length} available, " +
408
- "#{@checked_out_connections.length} checked out, " +
409
- "#{@pending_connections.length} pending " +
410
- "(max size: #{max_size})"
411
- end
412
- raise Error::ConnectionCheckOutTimeout.new(msg, address: @server.address)
413
- end
414
- @available_semaphore.wait(wait)
415
- end
416
- end
417
-
418
- begin
419
- connect_connection(connection)
420
- rescue Exception
421
- # Handshake or authentication failed
422
- @lock.synchronize do
423
- @pending_connections.delete(connection)
424
- end
425
- @populate_semaphore.signal
426
-
427
- publish_cmap_event(
428
- Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
429
- @server.address,
430
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
431
- ),
432
- )
433
- raise
434
- end
435
-
436
- @lock.synchronize do
437
- @checked_out_connections << connection
438
- @pending_connections.delete(connection)
439
- end
365
+ connection = retrieve_and_connect_connection(connection_global_id)
440
366
 
441
367
  publish_cmap_event(
442
368
  Monitoring::Event::Cmap::ConnectionCheckedOut.new(@server.address, connection.id, self),
@@ -464,69 +390,114 @@ module Mongo
464
390
  check_invariants
465
391
 
466
392
  @lock.synchronize do
467
- unless connection.connection_pool == self
468
- raise ArgumentError, "Trying to check in a connection which was not checked out by this pool: #{connection} checked out from pool #{connection.connection_pool} (for #{self})"
469
- end
393
+ do_check_in(connection)
394
+ end
395
+ ensure
396
+ check_invariants
397
+ end
470
398
 
471
- unless @checked_out_connections.include?(connection)
472
- raise ArgumentError, "Trying to check in a connection which is not currently checked out by this pool: #{connection} (for #{self})"
473
- end
399
+ # Executes the check in after having already acquired the lock.
400
+ #
401
+ # @param [ Mongo::Server::Connection ] connection The connection.
402
+ def do_check_in(connection)
403
+ # When a connection is interrupted it is checked back into the pool
404
+ # and closed. The operation that was using the connection before it was
405
+ # interrupted will attempt to check it back into the pool, and we
406
+ # should ignore it since its already been closed and removed from the pool.
407
+ return if connection.closed? && connection.interrupted?
408
+
409
+ unless connection.connection_pool == self
410
+ raise ArgumentError, "Trying to check in a connection which was not checked out by this pool: #{connection} checked out from pool #{connection.connection_pool} (for #{self})"
411
+ end
412
+
413
+ unless @checked_out_connections.include?(connection)
414
+ raise ArgumentError, "Trying to check in a connection which is not currently checked out by this pool: #{connection} (for #{self})"
415
+ end
474
416
 
475
- # Note: if an event handler raises, resource will not be signaled.
476
- # This means threads waiting for a connection to free up when
477
- # the pool is at max size may time out.
478
- # Threads that begin waiting after this method completes (with
479
- # the exception) should be fine.
417
+ # Note: if an event handler raises, resource will not be signaled.
418
+ # This means threads waiting for a connection to free up when
419
+ # the pool is at max size may time out.
420
+ # Threads that begin waiting after this method completes (with
421
+ # the exception) should be fine.
480
422
 
481
- @checked_out_connections.delete(connection)
482
- publish_cmap_event(
483
- Monitoring::Event::Cmap::ConnectionCheckedIn.new(@server.address, connection.id, self)
484
- )
423
+ @checked_out_connections.delete(connection)
424
+ @size_cv.signal
485
425
 
486
- if connection.error?
487
- connection.disconnect!(reason: :error)
488
- return
489
- end
426
+ publish_cmap_event(
427
+ Monitoring::Event::Cmap::ConnectionCheckedIn.new(@server.address, connection.id, self)
428
+ )
490
429
 
491
- if closed?
492
- connection.disconnect!(reason: :pool_closed)
493
- return
494
- end
430
+ if connection.interrupted?
431
+ connection.disconnect!(reason: :stale)
432
+ return
433
+ end
495
434
 
496
- if connection.closed?
497
- # Connection was closed - for example, because it experienced
498
- # a network error. Nothing else needs to be done here.
499
- @populate_semaphore.signal
500
- elsif connection.generation != generation(service_id: connection.service_id) && !connection.pinned?
501
- # If connection is marked as pinned, it is used by a transaction
502
- # or a series of cursor operations in a load balanced setup.
503
- # In this case connection should not be disconnected until
504
- # unpinned.
505
- connection.disconnect!(reason: :stale)
506
- @populate_semaphore.signal
507
- else
508
- connection.record_checkin!
509
- @available_connections << connection
435
+ if connection.error?
436
+ connection.disconnect!(reason: :error)
437
+ return
438
+ end
510
439
 
511
- # Wake up only one thread waiting for an available connection,
512
- # since only one connection was checked in.
513
- @available_semaphore.signal
514
- end
440
+ if closed?
441
+ connection.disconnect!(reason: :pool_closed)
442
+ return
443
+ end
444
+
445
+ if connection.closed?
446
+ # Connection was closed - for example, because it experienced
447
+ # a network error. Nothing else needs to be done here.
448
+ @populate_semaphore.signal
449
+ elsif connection.generation != generation(service_id: connection.service_id) && !connection.pinned?
450
+ # If connection is marked as pinned, it is used by a transaction
451
+ # or a series of cursor operations in a load balanced setup.
452
+ # In this case connection should not be disconnected until
453
+ # unpinned.
454
+ connection.disconnect!(reason: :stale)
455
+ @populate_semaphore.signal
456
+ else
457
+ connection.record_checkin!
458
+ @available_connections << connection
459
+
460
+ @max_connecting_cv.signal
461
+ end
462
+ end
463
+
464
+ # Mark the connection pool as paused.
465
+ def pause
466
+ raise_if_closed!
467
+
468
+ check_invariants
469
+
470
+ @lock.synchronize do
471
+ do_pause
515
472
  end
516
473
  ensure
517
474
  check_invariants
518
475
  end
519
476
 
477
+ # Mark the connection pool as paused without acquiring the lock.
478
+ #
479
+ # @api private
480
+ def do_pause
481
+ if Lint.enabled? && !@server.unknown?
482
+ raise Error::LintError, "Attempting to pause pool for server #{@server.summary} which is known"
483
+ end
484
+
485
+ return if !@ready
486
+
487
+ @ready = false
488
+ end
489
+
520
490
  # Closes all idle connections in the pool and schedules currently checked
521
491
  # out connections to be closed when they are checked back into the pool.
522
- # The pool remains operational and can create new connections when
523
- # requested.
492
+ # The pool is paused, it will not create new connections in background
493
+ # and it will fail checkout requests until marked ready.
524
494
  #
525
495
  # @option options [ true | false ] :lazy If true, do not close any of
526
496
  # the idle connections and instead let them be closed during a
527
- # subsequent check out operation.
528
- # @option options [ true | false ] :stop_populator Whether to stop
529
- # the populator background thread. For internal driver use only.
497
+ # subsequent check out operation. Defaults to false.
498
+ # @option options [ true | false ] :interrupt_in_use_connections If true,
499
+ # close all checked out connections immediately. If it is false, do not
500
+ # close any of the checked out connections. Defaults to true.
530
501
  # @option options [ Object ] :service_id Clear connections with
531
502
  # the specified service id only.
532
503
  #
@@ -536,56 +507,112 @@ module Mongo
536
507
  def clear(options = nil)
537
508
  raise_if_closed!
538
509
 
539
- check_invariants
540
-
541
- if options && options[:stop_populator]
542
- stop_populator
510
+ if Lint.enabled? && !@server.unknown?
511
+ raise Error::LintError, "Attempting to clear pool for server #{@server.summary} which is known"
543
512
  end
544
513
 
514
+ do_clear(options)
515
+ end
516
+
517
+ # Disconnects the pool.
518
+ #
519
+ # Does everything that +clear+ does, except if the pool is closed
520
+ # this method does nothing but +clear+ would raise PoolClosedError.
521
+ #
522
+ # @since 2.1.0
523
+ # @api private
524
+ def disconnect!(options = nil)
525
+ do_clear(options)
526
+ rescue Error::PoolClosedError
527
+ # The "disconnected" state is between closed and paused.
528
+ # When we are trying to disconnect the pool, permit the pool to be
529
+ # already closed.
530
+ end
531
+
532
+ def do_clear(options = nil)
533
+ check_invariants
534
+
545
535
  service_id = options && options[:service_id]
546
536
 
547
537
  @lock.synchronize do
538
+ # Generation must be bumped before emitting pool cleared event.
548
539
  @generation_manager.bump(service_id: service_id)
549
540
 
550
- publish_cmap_event(
551
- Monitoring::Event::Cmap::PoolCleared.new(
552
- @server.address,
553
- service_id: service_id
554
- )
555
- )
556
-
557
541
  unless options && options[:lazy]
558
- if @server.load_balancer? && service_id
559
- loop do
560
- conn = @available_connections.detect do |conn|
561
- conn.service_id == service_id
562
- end
563
- if conn
564
- @available_connections.delete(conn)
565
- conn.disconnect!(reason: :stale)
566
- @populate_semaphore.signal
567
- else
568
- break
569
- end
570
- end
571
- else
572
- until @available_connections.empty?
573
- connection = @available_connections.pop
574
- connection.disconnect!(reason: :stale)
575
- @populate_semaphore.signal
576
- end
577
- end
542
+ close_available_connections(service_id)
543
+ end
544
+
545
+ if options && options[:interrupt_in_use_connections]
546
+ schedule_for_interruption(@checked_out_connections, service_id)
547
+ schedule_for_interruption(@pending_connections, service_id)
548
+ end
549
+
550
+ if @ready
551
+ publish_cmap_event(
552
+ Monitoring::Event::Cmap::PoolCleared.new(
553
+ @server.address,
554
+ service_id: service_id,
555
+ interrupt_in_use_connections: options&.[](:interrupt_in_use_connections)
556
+ )
557
+ )
558
+ # Only pause the connection pool if the server was marked unknown,
559
+ # otherwise, allow the retry to be attempted with a ready pool.
560
+ do_pause if !@server.load_balancer? && @server.unknown?
578
561
  end
562
+
563
+ # Broadcast here to cause all of the threads waiting on the max
564
+ # connecting to break out of the wait loop and error.
565
+ @max_connecting_cv.broadcast
566
+ # Broadcast here to cause all of the threads waiting on the pool size
567
+ # to break out of the wait loop and error.
568
+ @size_cv.broadcast
579
569
  end
580
570
 
571
+ # "Schedule the background thread" after clearing. This is responsible
572
+ # for cleaning up stale threads, and interrupting in use connections.
573
+ @populate_semaphore.signal
581
574
  true
582
575
  ensure
583
576
  check_invariants
584
577
  end
585
578
 
586
- # @since 2.1.0
587
- # @deprecated
588
- alias :disconnect! :clear
579
+ # Instructs the pool to create and return connections.
580
+ def ready
581
+ raise_if_closed!
582
+
583
+ # TODO: Add this back in RUBY-3174.
584
+ # if Lint.enabled?
585
+ # unless @server.connected?
586
+ # raise Error::LintError, "Attempting to ready a pool for server #{@server.summary} which is disconnected"
587
+ # end
588
+ # end
589
+
590
+ @lock.synchronize do
591
+ return if @ready
592
+
593
+ @ready = true
594
+ end
595
+
596
+ # Note that the CMAP spec demands serialization of CMAP events for a
597
+ # pool. In order to implement this, event publication must be done into
598
+ # a queue which is synchronized, instead of subscribers being invoked
599
+ # from the trigger method like this one here inline. On MRI, assuming
600
+ # the threads yield to others when they stop having work to do, it is
601
+ # likely that the events would in practice always be published in the
602
+ # required order. JRuby, being truly concurrent with OS threads,
603
+ # would not offers such a guarantee.
604
+ publish_cmap_event(
605
+ Monitoring::Event::Cmap::PoolReady.new(@server.address, options, self)
606
+ )
607
+
608
+ if options.fetch(:populator_io, true)
609
+ if @populator.running?
610
+ @populate_semaphore.signal
611
+ else
612
+ @populator.run!
613
+ end
614
+ end
615
+ end
589
616
 
590
617
  # Marks the pool closed, closes all idle connections in the pool and
591
618
  # schedules currently checked out connections to be closed when they are
@@ -595,6 +622,8 @@ module Mongo
595
622
  #
596
623
  # @option options [ true | false ] :force Also close all checked out
597
624
  # connections.
625
+ # @option options [ true | false ] :stay_ready For internal driver use
626
+ # only. Whether or not to mark the pool as closed.
598
627
  #
599
628
  # @return [ true ] Always true.
600
629
  #
@@ -620,9 +649,15 @@ module Mongo
620
649
  end
621
650
  end
622
651
 
623
- # mark pool as closed before releasing lock so
624
- # no connections can be created, checked in, or checked out
625
- @closed = true
652
+ unless options && options[:stay_ready]
653
+ # mark pool as closed before releasing lock so
654
+ # no connections can be created, checked in, or checked out
655
+ @closed = true
656
+ @ready = false
657
+ end
658
+
659
+ @max_connecting_cv.broadcast
660
+ @size_cv.broadcast
626
661
  end
627
662
 
628
663
  publish_cmap_event(
@@ -644,6 +679,9 @@ module Mongo
644
679
  if closed?
645
680
  "#<Mongo::Server::ConnectionPool:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
646
681
  "wait_timeout=#{wait_timeout} closed>"
682
+ elsif !ready?
683
+ "#<Mongo::Server::ConnectionPool:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
684
+ "wait_timeout=#{wait_timeout} paused>"
647
685
  else
648
686
  "#<Mongo::Server::ConnectionPool:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
649
687
  "wait_timeout=#{wait_timeout} current_size=#{size} available=#{available_count}>"
@@ -665,6 +703,8 @@ module Mongo
665
703
 
666
704
  connection = check_out(connection_global_id: connection_global_id)
667
705
  yield(connection)
706
+ rescue Error::SocketError, Error::SocketTimeoutError, Error::ConnectionPerished => e
707
+ maybe_raise_pool_cleared!(connection, e)
668
708
  ensure
669
709
  if connection
670
710
  check_in(connection)
@@ -713,17 +753,17 @@ module Mongo
713
753
  # connections waiting to be connected, connections which have not yet
714
754
  # been moved to available_connections, or connections moved to available_connections
715
755
  # but not deleted from pending_connections. These should be cleaned up.
716
- until @pending_connections.empty?
717
- connection = @pending_connections.take(1).first
718
- connection.disconnect!
719
- @pending_connections.delete(connection)
720
- end
756
+ clear_pending_connections
721
757
  end
722
758
  end
723
759
 
724
- # Creates and adds a connection to the pool, if the pool's size is below
725
- # min_size. Retries once if a socket-related error is encountered during
726
- # this process and raises if a second error or a non socket-related error occurs.
760
+ # This method does three things:
761
+ # 1. Creates and adds a connection to the pool, if the pool's size is
762
+ # below min_size. Retries once if a socket-related error is
763
+ # encountered during this process and raises if a second error or a
764
+ # non socket-related error occurs.
765
+ # 2. Removes stale connections from the connection pool.
766
+ # 3. Interrupts connections marked for interruption.
727
767
  #
728
768
  # Used by the pool populator background thread.
729
769
  #
@@ -745,11 +785,6 @@ module Mongo
745
785
  end
746
786
 
747
787
  return create_and_add_connection
748
- rescue Error::AuthError, Error
749
- # wake up one thread waiting for connections, since one could not
750
- # be created here, and can instead be created in flow
751
- @available_semaphore.signal
752
- raise
753
788
  end
754
789
 
755
790
  # Finalize the connection pool for garbage collection.
@@ -782,7 +817,9 @@ module Mongo
782
817
  # Returns the next available connection, optionally with given
783
818
  # global id. If no suitable connections are available,
784
819
  # returns nil.
785
- def next_available_connection(connection_global_id: nil)
820
+ def next_available_connection(connection_global_id)
821
+ raise_unless_locked!
822
+
786
823
  if @server.load_balancer? && connection_global_id
787
824
  conn = @available_connections.detect do |conn|
788
825
  conn.global_id == connection_global_id
@@ -797,18 +834,21 @@ module Mongo
797
834
  end
798
835
 
799
836
  def create_connection
837
+ r, _ = @generation_manager.pipe_fds(service_id: server.description.service_id)
800
838
  opts = options.merge(
801
839
  connection_pool: self,
840
+ pipe: r
802
841
  # Do not pass app metadata - this will be retrieved by the connection
803
842
  # based on the auth needs.
804
843
  )
805
844
  unless @server.load_balancer?
806
845
  opts[:generation] = generation
807
846
  end
808
- connection = Connection.new(@server, opts)
847
+ Connection.new(@server, opts)
809
848
  end
810
849
 
811
- # Create a connection, connect it, and add it to the pool.
850
+ # Create a connection, connect it, and add it to the pool. Also
851
+ # check for stale and interruptable connections and deal with them.
812
852
  #
813
853
  # @return [ true | false ] True if a connection was created and
814
854
  # added to the pool, false otherwise
@@ -817,10 +857,15 @@ module Mongo
817
857
  connection = nil
818
858
 
819
859
  @lock.synchronize do
820
- if !closed? && unsynchronized_size < min_size
860
+ if !closed? && @ready &&
861
+ (unsynchronized_size + @connection_requests) < min_size &&
862
+ @pending_connections.length < @max_connecting
863
+ then
821
864
  connection = create_connection
822
865
  @pending_connections << connection
823
866
  else
867
+ return true if remove_interrupted_connections
868
+ return true if remove_stale_connection
824
869
  return false
825
870
  end
826
871
  end
@@ -830,6 +875,8 @@ module Mongo
830
875
  rescue Exception
831
876
  @lock.synchronize do
832
877
  @pending_connections.delete(connection)
878
+ @max_connecting_cv.signal
879
+ @size_cv.signal
833
880
  end
834
881
  raise
835
882
  end
@@ -837,14 +884,65 @@ module Mongo
837
884
  @lock.synchronize do
838
885
  @available_connections << connection
839
886
  @pending_connections.delete(connection)
887
+ @max_connecting_cv.signal
888
+ @size_cv.signal
889
+ end
890
+
891
+ true
892
+ end
893
+
894
+ # Removes and disconnects all stale available connections.
895
+ def remove_stale_connection
896
+ if conn = @available_connections.detect(&method(:connection_stale_unlocked?))
897
+ conn.disconnect!(reason: :stale)
898
+ @available_connections.delete(conn)
899
+ return true
900
+ end
901
+ end
902
+
903
+ # Interrupt connections scheduled for interruption.
904
+ def remove_interrupted_connections
905
+ return false if @interrupt_connections.empty?
906
+
907
+ gens = Set.new
908
+ while conn = @interrupt_connections.pop
909
+ if @checked_out_connections.include?(conn)
910
+ # If the connection has been checked out, mark it as interrupted and it will
911
+ # be disconnected on check in.
912
+ conn.interrupted!
913
+ do_check_in(conn)
914
+ elsif @pending_connections.include?(conn)
915
+ # If the connection is pending, disconnect with the interrupted flag.
916
+ conn.disconnect!(reason: :stale, interrupted: true)
917
+ @pending_connections.delete(conn)
918
+ end
919
+ gens << [ conn.generation, conn.service_id ]
920
+ end
840
921
 
841
- # wake up one thread waiting for connections, since one was created
842
- @available_semaphore.signal
922
+ # Close the write side of the pipe. Pending connections might be
923
+ # hanging on the Kernel#select call, so in order to interrupt that,
924
+ # we also listen for the read side of the pipe in Kernel#select and
925
+ # close the write side of the pipe here, which will cause select to
926
+ # wake up and raise an IOError now that the socket is closed.
927
+ # The read side of the pipe will be scheduled for closing on the next
928
+ # generation bump.
929
+ gens.each do |gen, service_id|
930
+ @generation_manager.remove_pipe_fds(gen, service_id: service_id)
843
931
  end
844
932
 
845
933
  true
846
934
  end
847
935
 
936
+ # Checks whether a connection is stale.
937
+ #
938
+ # @param [ Mongo::Server::Connection ] connection The connection to check.
939
+ #
940
+ # @return [ true | false ] Whether the connection is stale.
941
+ def connection_stale_unlocked?(connection)
942
+ connection.generation != generation_unlocked(service_id: connection.service_id) &&
943
+ !connection.pinned?
944
+ end
945
+
848
946
  # Asserts that the pool has not been closed.
849
947
  #
850
948
  # @raise [ Error::PoolClosedError ] If the pool has been closed.
@@ -856,6 +954,25 @@ module Mongo
856
954
  end
857
955
  end
858
956
 
957
+ # If the connection was interrupted, raise a pool cleared error. If it
958
+ # wasn't interrupted raise the original error.
959
+ #
960
+ # @param [ Connection ] The connection.
961
+ # @param [ Mongo::Error ] The original error.
962
+ #
963
+ # @raise [ Mongo::Error | Mongo::Error::PoolClearedError ] A PoolClearedError
964
+ # if the connection was interrupted, the original error if not.
965
+ def maybe_raise_pool_cleared!(connection, e)
966
+ if connection&.interrupted?
967
+ err = Error::PoolClearedError.new(connection.server.address, connection.server.pool_internal).tap do |err|
968
+ e.labels.each { |l| err.add_label(l) }
969
+ end
970
+ raise err
971
+ else
972
+ raise e
973
+ end
974
+ end
975
+
859
976
  # Attempts to connect (handshake and auth) the connection. If an error is
860
977
  # encountered, closes the connection and raises the error.
861
978
  def connect_connection(connection)
@@ -895,6 +1012,350 @@ module Mongo
895
1012
  end
896
1013
  end
897
1014
  end
1015
+
1016
+ # Close the available connections.
1017
+ #
1018
+ # @param [ Array<Connection> ] connections A list of connections.
1019
+ # @param [ Object ] service_id The service id.
1020
+ def close_available_connections(service_id)
1021
+ if @server.load_balancer? && service_id
1022
+ loop do
1023
+ conn = @available_connections.detect do |conn|
1024
+ conn.service_id == service_id &&
1025
+ conn.generation < @generation_manager.generation(service_id: service_id)
1026
+ end
1027
+ if conn
1028
+ @available_connections.delete(conn)
1029
+ conn.disconnect!(reason: :stale, interrupted: true)
1030
+ @populate_semaphore.signal
1031
+ else
1032
+ break
1033
+ end
1034
+ end
1035
+ else
1036
+ @available_connections.delete_if do |conn|
1037
+ if conn.generation < @generation_manager.generation(service_id: service_id)
1038
+ conn.disconnect!(reason: :stale, interrupted: true)
1039
+ @populate_semaphore.signal
1040
+ true
1041
+ end
1042
+ end
1043
+ end
1044
+ end
1045
+
1046
+ # Schedule connections of previous generations for interruption.
1047
+ #
1048
+ # @param [ Array<Connection> ] connections A list of connections.
1049
+ # @param [ Object ] service_id The service id.
1050
+ def schedule_for_interruption(connections, service_id)
1051
+ @interrupt_connections += connections.select do |conn|
1052
+ (!server.load_balancer? || conn.service_id == service_id) &&
1053
+ conn.generation < @generation_manager.generation(service_id: service_id)
1054
+ end
1055
+ end
1056
+
1057
+ # Clear and disconnect the pending connections.
1058
+ def clear_pending_connections
1059
+ until @pending_connections.empty?
1060
+ connection = @pending_connections.take(1).first
1061
+ connection.disconnect!
1062
+ @pending_connections.delete(connection)
1063
+ end
1064
+ end
1065
+
1066
+ # The lock should be acquired when calling this method.
1067
+ def raise_check_out_timeout!(connection_global_id)
1068
+ raise_unless_locked!
1069
+
1070
+ publish_cmap_event(
1071
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1072
+ @server.address,
1073
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::TIMEOUT,
1074
+ ),
1075
+ )
1076
+
1077
+ connection_global_id_msg = if connection_global_id
1078
+ " for connection #{connection_global_id}"
1079
+ else
1080
+ ''
1081
+ end
1082
+
1083
+ msg = "Timed out attempting to check out a connection " +
1084
+ "from pool for #{@server.address}#{connection_global_id_msg} after #{wait_timeout} sec. " +
1085
+ "Connections in pool: #{@available_connections.length} available, " +
1086
+ "#{@checked_out_connections.length} checked out, " +
1087
+ "#{@pending_connections.length} pending, " +
1088
+ "#{@connection_requests} connections requests " +
1089
+ "(max size: #{max_size})"
1090
+ raise Error::ConnectionCheckOutTimeout.new(msg, address: @server.address)
1091
+ end
1092
+
1093
+ def raise_check_out_timeout_locked!(connection_global_id)
1094
+ @lock.synchronize do
1095
+ raise_check_out_timeout!(connection_global_id)
1096
+ end
1097
+ end
1098
+
1099
+ def raise_if_pool_closed!
1100
+ if closed?
1101
+ publish_cmap_event(
1102
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1103
+ @server.address,
1104
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::POOL_CLOSED
1105
+ ),
1106
+ )
1107
+ raise Error::PoolClosedError.new(@server.address, self)
1108
+ end
1109
+ end
1110
+
1111
+ def raise_if_pool_paused!
1112
+ raise_unless_locked!
1113
+
1114
+ if !@ready
1115
+ publish_cmap_event(
1116
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1117
+ @server.address,
1118
+ # CMAP spec decided to conflate pool paused with all the other
1119
+ # possible non-timeout errors.
1120
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR,
1121
+ ),
1122
+ )
1123
+ raise Error::PoolPausedError.new(@server.address, self)
1124
+ end
1125
+ end
1126
+
1127
+ def raise_if_pool_paused_locked!
1128
+ @lock.synchronize do
1129
+ raise_if_pool_paused!
1130
+ end
1131
+ end
1132
+
1133
+ # The lock should be acquired when calling this method.
1134
+ def raise_if_not_ready!
1135
+ raise_unless_locked!
1136
+ raise_if_pool_closed!
1137
+ raise_if_pool_paused!
1138
+ end
1139
+
1140
+ def raise_unless_locked!
1141
+ unless @lock.owned?
1142
+ raise ArgumentError, "the lock must be owned when calling this method"
1143
+ end
1144
+ end
1145
+
1146
+ def valid_available_connection?(connection, pid, connection_global_id)
1147
+ if connection.pid != pid
1148
+ log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{connection.pid}, new pid #{pid}")
1149
+ connection.disconnect!(reason: :stale)
1150
+ @populate_semaphore.signal
1151
+ return false
1152
+ end
1153
+
1154
+ if !connection.pinned?
1155
+ # If connection is marked as pinned, it is used by a transaction
1156
+ # or a series of cursor operations in a load balanced setup.
1157
+ # In this case connection should not be disconnected until
1158
+ # unpinned.
1159
+ if connection.generation != generation(
1160
+ service_id: connection.service_id
1161
+ )
1162
+ # Stale connections should be disconnected in the clear
1163
+ # method, but if any don't, check again here
1164
+ connection.disconnect!(reason: :stale)
1165
+ @populate_semaphore.signal
1166
+ return false
1167
+ end
1168
+
1169
+ if max_idle_time && connection.last_checkin &&
1170
+ Time.now - connection.last_checkin > max_idle_time
1171
+ then
1172
+ connection.disconnect!(reason: :idle)
1173
+ @populate_semaphore.signal
1174
+ return false
1175
+ end
1176
+ end
1177
+ true
1178
+ end
1179
+
1180
+ # Retrieves a connection if one is available, otherwise we create a new
1181
+ # one. If no connection exists and the pool is at max size, wait until
1182
+ # a connection is checked back into the pool.
1183
+ #
1184
+ # @param [ Integer ] pid The current process id.
1185
+ # @param [ Integer ] connection_global_id The global id for the
1186
+ # connection to check out.
1187
+ #
1188
+ # @return [ Mongo::Server::Connection ] The checked out connection.
1189
+ #
1190
+ # @raise [ Error::PoolClosedError ] If the pool has been closed.
1191
+ # @raise [ Timeout::Error ] If the connection pool is at maximum size
1192
+ # and remains so for longer than the wait timeout.
1193
+ def get_connection(pid, connection_global_id)
1194
+ if connection = next_available_connection(connection_global_id)
1195
+ unless valid_available_connection?(connection, pid, connection_global_id)
1196
+ return nil
1197
+ end
1198
+
1199
+ # We've got a connection, so we decrement the number of connection
1200
+ # requests.
1201
+ # We do not need to signal condition variable here, because
1202
+ # because the execution will continue, and we signal later.
1203
+ @connection_requests -= 1
1204
+
1205
+ # If the connection is connected, it's not considered a
1206
+ # "pending connection". The pending_connections list represents
1207
+ # the set of connections that are awaiting connection.
1208
+ unless connection.connected?
1209
+ @pending_connections << connection
1210
+ end
1211
+ return connection
1212
+ elsif connection_global_id && @server.load_balancer?
1213
+ # A particular connection is requested, but it is not available.
1214
+ # If it is nether available not checked out, we should stop here.
1215
+ @checked_out_connections.detect do |conn|
1216
+ conn.global_id == connection_global_id
1217
+ end.tap do |conn|
1218
+ if conn.nil?
1219
+ publish_cmap_event(
1220
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1221
+ @server.address,
1222
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
1223
+ ),
1224
+ )
1225
+ # We're going to raise, so we need to decrement the number of
1226
+ # connection requests.
1227
+ decrement_connection_requests_and_signal
1228
+ raise Error::MissingConnection.new
1229
+ end
1230
+ end
1231
+ # We need a particular connection, and if it is not available
1232
+ # we can wait for an in-progress operation to return
1233
+ # such a connection to the pool.
1234
+ nil
1235
+ else
1236
+ connection = create_connection
1237
+ @connection_requests -= 1
1238
+ @pending_connections << connection
1239
+ return connection
1240
+ end
1241
+ end
1242
+
1243
+ # Retrieves a connection and connects it.
1244
+ #
1245
+ # @param [ Integer ] connection_global_id The global id for the
1246
+ # connection to check out.
1247
+ #
1248
+ # @return [ Mongo::Server::Connection ] The checked out connection.
1249
+ #
1250
+ # @raise [ Error::PoolClosedError ] If the pool has been closed.
1251
+ # @raise [ Timeout::Error ] If the connection pool is at maximum size
1252
+ # and remains so for longer than the wait timeout.
1253
+ def retrieve_and_connect_connection(connection_global_id)
1254
+ deadline = Utils.monotonic_time + wait_timeout
1255
+ connection = nil
1256
+
1257
+ @lock.synchronize do
1258
+ # The first gate to checking out a connection. Make sure the number of
1259
+ # unavailable connections is less than the max pool size.
1260
+ until max_size == 0 || unavailable_connections < max_size
1261
+ wait = deadline - Utils.monotonic_time
1262
+ raise_check_out_timeout!(connection_global_id) if wait <= 0
1263
+ @size_cv.wait(wait)
1264
+ raise_if_not_ready!
1265
+ end
1266
+ @connection_requests += 1
1267
+ connection = wait_for_connection(connection_global_id, deadline)
1268
+ end
1269
+
1270
+ connect_or_raise(connection) unless connection.connected?
1271
+
1272
+ @lock.synchronize do
1273
+ @checked_out_connections << connection
1274
+ if @pending_connections.include?(connection)
1275
+ @pending_connections.delete(connection)
1276
+ end
1277
+ @max_connecting_cv.signal
1278
+ # no need to signal size_cv here since the number of unavailable
1279
+ # connections is unchanged.
1280
+ end
1281
+
1282
+ connection
1283
+ end
1284
+
1285
+ # Waits for a connection to become available, or raises is no connection
1286
+ # becomes available before the timeout.
1287
+ # @param [ Integer ] connection_global_id The global id for the
1288
+ # connection to check out.
1289
+ # @param [ Float ] deadline The time at which to stop waiting.
1290
+ #
1291
+ # @return [ Mongo::Server::Connection ] The checked out connection.
1292
+ def wait_for_connection(connection_global_id, deadline)
1293
+ connection = nil
1294
+ while connection.nil?
1295
+ # The second gate to checking out a connection. Make sure 1) there
1296
+ # exists an available connection and 2) we are under max_connecting.
1297
+ until @available_connections.any? || @pending_connections.length < @max_connecting
1298
+ wait = deadline - Utils.monotonic_time
1299
+ if wait <= 0
1300
+ # We are going to raise a timeout error, so the connection
1301
+ # request is not going to be fulfilled. Decrement the counter
1302
+ # here.
1303
+ decrement_connection_requests_and_signal
1304
+ raise_check_out_timeout!(connection_global_id)
1305
+ end
1306
+ @max_connecting_cv.wait(wait)
1307
+ # We do not need to decrement the connection_requests counter
1308
+ # or signal here because the pool is not ready yet.
1309
+ raise_if_not_ready!
1310
+ end
1311
+
1312
+ connection = get_connection(Process.pid, connection_global_id)
1313
+ wait = deadline - Utils.monotonic_time
1314
+ if connection.nil? && wait <= 0
1315
+ # connection is nil here, it means that get_connection method
1316
+ # did not create a new connection; therefore, it did not decrease
1317
+ # the connection_requests counter. We need to do it here.
1318
+ decrement_connection_requests_and_signal
1319
+ raise_check_out_timeout!(connection_global_id)
1320
+ end
1321
+ end
1322
+
1323
+ connection
1324
+ end
1325
+
1326
+ # Connects a connection and raises an exception if the connection
1327
+ # cannot be connected.
1328
+ # This method also publish corresponding event and ensures that counters
1329
+ # and condition variables are updated.
1330
+ def connect_or_raise(connection)
1331
+ connect_connection(connection)
1332
+ rescue Exception
1333
+ # Handshake or authentication failed
1334
+ @lock.synchronize do
1335
+ if @pending_connections.include?(connection)
1336
+ @pending_connections.delete(connection)
1337
+ end
1338
+ @max_connecting_cv.signal
1339
+ @size_cv.signal
1340
+ end
1341
+ @populate_semaphore.signal
1342
+ publish_cmap_event(
1343
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1344
+ @server.address,
1345
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
1346
+ ),
1347
+ )
1348
+ raise
1349
+ end
1350
+
1351
+
1352
+ # Decrement connection requests counter and signal the condition
1353
+ # variables that the number of unavailable connections has decreased.
1354
+ def decrement_connection_requests_and_signal
1355
+ @connection_requests -= 1
1356
+ @max_connecting_cv.signal
1357
+ @size_cv.signal
1358
+ end
898
1359
  end
899
1360
  end
900
1361
  end