mongo 2.22.0 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mongo_console +0 -1
  3. data/lib/mongo/active_support.rb +1 -2
  4. data/lib/mongo/address/ipv4.rb +3 -6
  5. data/lib/mongo/address/ipv6.rb +6 -10
  6. data/lib/mongo/address/unix.rb +1 -4
  7. data/lib/mongo/address/validator.rb +16 -28
  8. data/lib/mongo/address.rb +30 -40
  9. data/lib/mongo/auth/aws/conversation.rb +6 -10
  10. data/lib/mongo/auth/aws/credentials.rb +0 -1
  11. data/lib/mongo/auth/aws/credentials_cache.rb +0 -1
  12. data/lib/mongo/auth/aws/credentials_retriever.rb +45 -59
  13. data/lib/mongo/auth/aws/request.rb +20 -35
  14. data/lib/mongo/auth/aws.rb +1 -2
  15. data/lib/mongo/auth/base.rb +20 -29
  16. data/lib/mongo/auth/conversation_base.rb +14 -18
  17. data/lib/mongo/auth/cr/conversation.rb +0 -3
  18. data/lib/mongo/auth/cr.rb +1 -4
  19. data/lib/mongo/auth/credential_cache.rb +0 -2
  20. data/lib/mongo/auth/gssapi/conversation.rb +3 -8
  21. data/lib/mongo/auth/gssapi.rb +1 -4
  22. data/lib/mongo/auth/ldap/conversation.rb +0 -3
  23. data/lib/mongo/auth/ldap.rb +1 -4
  24. data/lib/mongo/auth/roles.rb +16 -19
  25. data/lib/mongo/auth/sasl_conversation_base.rb +7 -11
  26. data/lib/mongo/auth/scram/conversation.rb +2 -5
  27. data/lib/mongo/auth/scram.rb +5 -10
  28. data/lib/mongo/auth/scram256/conversation.rb +2 -5
  29. data/lib/mongo/auth/scram256.rb +1 -3
  30. data/lib/mongo/auth/scram_conversation_base.rb +18 -24
  31. data/lib/mongo/auth/stringprep/profiles/sasl.rb +17 -18
  32. data/lib/mongo/auth/stringprep/tables.rb +2209 -2210
  33. data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +36 -38
  34. data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +1142 -1150
  35. data/lib/mongo/auth/stringprep.rb +9 -12
  36. data/lib/mongo/auth/user/view.rb +3 -5
  37. data/lib/mongo/auth/user.rb +14 -24
  38. data/lib/mongo/auth/x509/conversation.rb +0 -3
  39. data/lib/mongo/auth/x509.rb +7 -9
  40. data/lib/mongo/auth.rb +18 -30
  41. data/lib/mongo/background_thread.rb +9 -17
  42. data/lib/mongo/bson.rb +0 -2
  43. data/lib/mongo/bulk_write/combineable.rb +0 -3
  44. data/lib/mongo/bulk_write/ordered_combiner.rb +1 -3
  45. data/lib/mongo/bulk_write/result.rb +11 -16
  46. data/lib/mongo/bulk_write/result_combiner.rb +9 -12
  47. data/lib/mongo/bulk_write/transformable.rb +16 -19
  48. data/lib/mongo/bulk_write/unordered_combiner.rb +1 -3
  49. data/lib/mongo/bulk_write/validatable.rb +11 -18
  50. data/lib/mongo/bulk_write.rb +76 -91
  51. data/lib/mongo/caching_cursor.rb +2 -7
  52. data/lib/mongo/client.rb +267 -276
  53. data/lib/mongo/client_encryption.rb +4 -5
  54. data/lib/mongo/cluster/periodic_executor.rb +2 -5
  55. data/lib/mongo/cluster/reapers/cursor_reaper.rb +21 -29
  56. data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -6
  57. data/lib/mongo/cluster/sdam_flow.rb +136 -159
  58. data/lib/mongo/cluster/topology/base.rb +15 -18
  59. data/lib/mongo/cluster/topology/load_balanced.rb +24 -14
  60. data/lib/mongo/cluster/topology/no_replica_set_options.rb +3 -6
  61. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +20 -23
  62. data/lib/mongo/cluster/topology/replica_set_with_primary.rb +0 -2
  63. data/lib/mongo/cluster/topology/sharded.rb +19 -9
  64. data/lib/mongo/cluster/topology/single.rb +24 -14
  65. data/lib/mongo/cluster/topology/unknown.rb +20 -10
  66. data/lib/mongo/cluster/topology.rb +29 -25
  67. data/lib/mongo/cluster.rb +152 -184
  68. data/lib/mongo/cluster_time.rb +14 -31
  69. data/lib/mongo/collection/helpers.rb +5 -8
  70. data/lib/mongo/collection/view/aggregation/behavior.rb +1 -1
  71. data/lib/mongo/collection/view/aggregation.rb +10 -12
  72. data/lib/mongo/collection/view/builder/aggregation.rb +6 -9
  73. data/lib/mongo/collection/view/builder/map_reduce.rb +18 -17
  74. data/lib/mongo/collection/view/builder.rb +0 -1
  75. data/lib/mongo/collection/view/change_stream/retryable.rb +3 -8
  76. data/lib/mongo/collection/view/change_stream.rb +59 -58
  77. data/lib/mongo/collection/view/explainable.rb +11 -20
  78. data/lib/mongo/collection/view/immutable.rb +1 -3
  79. data/lib/mongo/collection/view/iterable.rb +44 -35
  80. data/lib/mongo/collection/view/map_reduce.rb +20 -25
  81. data/lib/mongo/collection/view/readable.rb +96 -94
  82. data/lib/mongo/collection/view/writable.rb +104 -114
  83. data/lib/mongo/collection/view.rb +11 -8
  84. data/lib/mongo/collection.rb +103 -106
  85. data/lib/mongo/condition_variable.rb +4 -4
  86. data/lib/mongo/config/options.rb +0 -3
  87. data/lib/mongo/config/validators/option.rb +3 -5
  88. data/lib/mongo/config.rb +6 -4
  89. data/lib/mongo/crypt/auto_decryption_context.rb +9 -3
  90. data/lib/mongo/crypt/auto_encrypter.rb +34 -43
  91. data/lib/mongo/crypt/auto_encryption_context.rb +0 -3
  92. data/lib/mongo/crypt/binary.rb +5 -9
  93. data/lib/mongo/crypt/binding.rb +150 -156
  94. data/lib/mongo/crypt/context.rb +20 -17
  95. data/lib/mongo/crypt/data_key_context.rb +2 -7
  96. data/lib/mongo/crypt/encryption_io.rb +29 -39
  97. data/lib/mongo/crypt/explicit_decryption_context.rb +9 -3
  98. data/lib/mongo/crypt/explicit_encrypter.rb +1 -1
  99. data/lib/mongo/crypt/explicit_encryption_context.rb +19 -30
  100. data/lib/mongo/crypt/explicit_encryption_expression_context.rb +0 -2
  101. data/lib/mongo/crypt/handle.rb +42 -48
  102. data/lib/mongo/crypt/hooks.rb +12 -15
  103. data/lib/mongo/crypt/kms/aws/credentials.rb +12 -16
  104. data/lib/mongo/crypt/kms/aws/master_document.rb +6 -9
  105. data/lib/mongo/crypt/kms/aws.rb +0 -2
  106. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +2 -7
  107. data/lib/mongo/crypt/kms/azure/master_document.rb +15 -19
  108. data/lib/mongo/crypt/kms/azure.rb +0 -1
  109. data/lib/mongo/crypt/kms/credentials.rb +13 -27
  110. data/lib/mongo/crypt/kms/gcp/credentials.rb +12 -14
  111. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +7 -9
  112. data/lib/mongo/crypt/kms/gcp/master_document.rb +12 -16
  113. data/lib/mongo/crypt/kms/gcp.rb +0 -2
  114. data/lib/mongo/crypt/kms/kmip/credentials.rb +7 -8
  115. data/lib/mongo/crypt/kms/kmip/master_document.rb +3 -5
  116. data/lib/mongo/crypt/kms/kmip.rb +0 -1
  117. data/lib/mongo/crypt/kms/local/credentials.rb +7 -8
  118. data/lib/mongo/crypt/kms/local/master_document.rb +2 -6
  119. data/lib/mongo/crypt/kms/local.rb +0 -1
  120. data/lib/mongo/crypt/kms/master_key_document.rb +11 -15
  121. data/lib/mongo/crypt/kms.rb +14 -16
  122. data/lib/mongo/crypt/kms_context.rb +0 -2
  123. data/lib/mongo/crypt/rewrap_many_data_key_context.rb +2 -7
  124. data/lib/mongo/crypt/rewrap_many_data_key_result.rb +2 -4
  125. data/lib/mongo/crypt/status.rb +12 -14
  126. data/lib/mongo/crypt.rb +0 -1
  127. data/lib/mongo/csot_timeout_holder.rb +3 -2
  128. data/lib/mongo/cursor/kill_spec.rb +7 -10
  129. data/lib/mongo/cursor.rb +74 -64
  130. data/lib/mongo/cursor_host.rb +8 -10
  131. data/lib/mongo/database/view.rb +23 -39
  132. data/lib/mongo/database.rb +68 -65
  133. data/lib/mongo/dbref.rb +0 -1
  134. data/lib/mongo/deprecations.rb +98 -0
  135. data/lib/mongo/distinguishing_semaphore.rb +0 -1
  136. data/lib/mongo/error/auth_error.rb +0 -2
  137. data/lib/mongo/error/bad_load_balancer_target.rb +0 -2
  138. data/lib/mongo/error/bulk_write_error.rb +7 -10
  139. data/lib/mongo/error/change_stream_resumable.rb +0 -2
  140. data/lib/mongo/error/client_closed.rb +0 -2
  141. data/lib/mongo/error/closed_stream.rb +1 -4
  142. data/lib/mongo/error/connection_check_out_timeout.rb +3 -6
  143. data/lib/mongo/error/connection_perished.rb +0 -2
  144. data/lib/mongo/error/connection_unavailable.rb +0 -2
  145. data/lib/mongo/error/credential_check_error.rb +0 -2
  146. data/lib/mongo/error/crypt_error.rb +0 -2
  147. data/lib/mongo/error/extra_file_chunk.rb +1 -4
  148. data/lib/mongo/error/failed_string_prep_validation.rb +5 -6
  149. data/lib/mongo/error/file_not_found.rb +0 -3
  150. data/lib/mongo/error/handshake_error.rb +0 -2
  151. data/lib/mongo/error/insufficient_iteration_count.rb +1 -4
  152. data/lib/mongo/error/internal_driver_error.rb +0 -2
  153. data/lib/mongo/error/invalid_address.rb +0 -2
  154. data/lib/mongo/error/invalid_application_name.rb +0 -3
  155. data/lib/mongo/error/invalid_bulk_operation.rb +1 -4
  156. data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -4
  157. data/lib/mongo/error/invalid_collection_name.rb +1 -4
  158. data/lib/mongo/error/invalid_config_option.rb +0 -3
  159. data/lib/mongo/error/invalid_cursor_operation.rb +0 -2
  160. data/lib/mongo/error/invalid_database_name.rb +1 -4
  161. data/lib/mongo/error/invalid_document.rb +1 -4
  162. data/lib/mongo/error/invalid_file.rb +0 -3
  163. data/lib/mongo/error/invalid_file_revision.rb +0 -3
  164. data/lib/mongo/error/invalid_min_pool_size.rb +0 -3
  165. data/lib/mongo/error/invalid_nonce.rb +0 -3
  166. data/lib/mongo/error/invalid_read_concern.rb +2 -4
  167. data/lib/mongo/error/invalid_read_option.rb +0 -3
  168. data/lib/mongo/error/invalid_replacement_document.rb +2 -5
  169. data/lib/mongo/error/invalid_server_auth_host.rb +0 -2
  170. data/lib/mongo/error/invalid_server_auth_response.rb +0 -2
  171. data/lib/mongo/error/invalid_server_preference.rb +7 -16
  172. data/lib/mongo/error/invalid_session.rb +1 -4
  173. data/lib/mongo/error/invalid_signature.rb +0 -3
  174. data/lib/mongo/error/invalid_transaction_operation.rb +5 -8
  175. data/lib/mongo/error/invalid_txt_record.rb +0 -2
  176. data/lib/mongo/error/invalid_update_document.rb +2 -5
  177. data/lib/mongo/error/invalid_uri.rb +1 -4
  178. data/lib/mongo/error/invalid_write_concern.rb +2 -5
  179. data/lib/mongo/error/kms_error.rb +0 -2
  180. data/lib/mongo/error/labelable.rb +0 -3
  181. data/lib/mongo/error/lint_error.rb +0 -2
  182. data/lib/mongo/error/max_bson_size.rb +8 -11
  183. data/lib/mongo/error/max_message_size.rb +2 -5
  184. data/lib/mongo/error/mismatched_domain.rb +0 -2
  185. data/lib/mongo/error/missing_connection.rb +0 -2
  186. data/lib/mongo/error/missing_file_chunk.rb +0 -3
  187. data/lib/mongo/error/missing_password.rb +0 -2
  188. data/lib/mongo/error/missing_resume_token.rb +1 -4
  189. data/lib/mongo/error/missing_scram_server_signature.rb +2 -4
  190. data/lib/mongo/error/missing_service_id.rb +0 -2
  191. data/lib/mongo/error/mongocryptd_spawn_error.rb +0 -2
  192. data/lib/mongo/error/multi_index_drop.rb +0 -3
  193. data/lib/mongo/error/need_primary_server.rb +0 -2
  194. data/lib/mongo/error/no_server_available.rb +3 -8
  195. data/lib/mongo/error/no_service_connection_available.rb +1 -3
  196. data/lib/mongo/error/no_srv_records.rb +0 -2
  197. data/lib/mongo/error/notable.rb +8 -16
  198. data/lib/mongo/error/operation_failure.rb +22 -35
  199. data/lib/mongo/error/parser.rb +33 -75
  200. data/lib/mongo/error/pool_cleared_error.rb +1 -3
  201. data/lib/mongo/error/pool_closed_error.rb +0 -3
  202. data/lib/mongo/error/pool_error.rb +0 -3
  203. data/lib/mongo/error/pool_paused_error.rb +0 -2
  204. data/lib/mongo/error/raise_original_error.rb +1 -3
  205. data/lib/mongo/error/read_write_retryable.rb +14 -17
  206. data/lib/mongo/error/sdam_error_detection.rb +3 -5
  207. data/lib/mongo/error/server_api_conflict.rb +0 -2
  208. data/lib/mongo/error/server_certificate_revoked.rb +0 -2
  209. data/lib/mongo/error/server_not_usable.rb +0 -2
  210. data/lib/mongo/error/session_ended.rb +1 -3
  211. data/lib/mongo/error/session_not_materialized.rb +1 -3
  212. data/lib/mongo/error/sessions_not_supported.rb +1 -4
  213. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +1 -4
  214. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +1 -4
  215. data/lib/mongo/error/socket_error.rb +0 -2
  216. data/lib/mongo/error/socket_timeout_error.rb +0 -2
  217. data/lib/mongo/error/transactions_not_supported.rb +3 -6
  218. data/lib/mongo/error/unchangeable_collection_option.rb +1 -4
  219. data/lib/mongo/error/unexpected_chunk_length.rb +0 -3
  220. data/lib/mongo/error/unexpected_response.rb +1 -4
  221. data/lib/mongo/error/unknown_payload_type.rb +0 -3
  222. data/lib/mongo/error/unmet_dependency.rb +0 -2
  223. data/lib/mongo/error/unsupported_array_filters.rb +3 -24
  224. data/lib/mongo/error/unsupported_collation.rb +3 -24
  225. data/lib/mongo/error/unsupported_features.rb +0 -2
  226. data/lib/mongo/error/unsupported_message_type.rb +0 -2
  227. data/lib/mongo/error/unsupported_option.rb +19 -21
  228. data/lib/mongo/error/write_retryable.rb +0 -2
  229. data/lib/mongo/error.rb +10 -24
  230. data/lib/mongo/event/base.rb +0 -2
  231. data/lib/mongo/event/listeners.rb +0 -3
  232. data/lib/mongo/event/publisher.rb +0 -3
  233. data/lib/mongo/event/subscriber.rb +0 -4
  234. data/lib/mongo/event.rb +4 -6
  235. data/lib/mongo/grid/file/chunk.rb +7 -10
  236. data/lib/mongo/grid/file/info.rb +20 -24
  237. data/lib/mongo/grid/file.rb +7 -8
  238. data/lib/mongo/grid/fs_bucket.rb +40 -48
  239. data/lib/mongo/grid/stream/read.rb +25 -35
  240. data/lib/mongo/grid/stream/write.rb +17 -22
  241. data/lib/mongo/grid/stream.rb +2 -4
  242. data/lib/mongo/grid.rb +0 -1
  243. data/lib/mongo/id.rb +0 -1
  244. data/lib/mongo/index/view.rb +68 -58
  245. data/lib/mongo/index.rb +7 -10
  246. data/lib/mongo/lint.rb +31 -37
  247. data/lib/mongo/loggable.rb +5 -8
  248. data/lib/mongo/logger.rb +1 -7
  249. data/lib/mongo/monitoring/cmap_log_subscriber.rb +0 -2
  250. data/lib/mongo/monitoring/command_log_subscriber.rb +25 -33
  251. data/lib/mongo/monitoring/event/cmap/base.rb +0 -2
  252. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -4
  253. data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +0 -3
  254. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +1 -4
  255. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +2 -5
  256. data/lib/mongo/monitoring/event/cmap/connection_closed.rb +1 -4
  257. data/lib/mongo/monitoring/event/cmap/connection_created.rb +1 -4
  258. data/lib/mongo/monitoring/event/cmap/connection_ready.rb +1 -4
  259. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +0 -3
  260. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +1 -4
  261. data/lib/mongo/monitoring/event/cmap/pool_created.rb +1 -4
  262. data/lib/mongo/monitoring/event/cmap/pool_ready.rb +1 -4
  263. data/lib/mongo/monitoring/event/cmap.rb +0 -1
  264. data/lib/mongo/monitoring/event/command_failed.rb +5 -9
  265. data/lib/mongo/monitoring/event/command_started.rb +8 -12
  266. data/lib/mongo/monitoring/event/command_succeeded.rb +7 -15
  267. data/lib/mongo/monitoring/event/secure.rb +15 -20
  268. data/lib/mongo/monitoring/event/server_closed.rb +1 -4
  269. data/lib/mongo/monitoring/event/server_description_changed.rb +4 -8
  270. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +5 -10
  271. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +1 -4
  272. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +3 -8
  273. data/lib/mongo/monitoring/event/server_opening.rb +1 -4
  274. data/lib/mongo/monitoring/event/topology_changed.rb +2 -5
  275. data/lib/mongo/monitoring/event/topology_closed.rb +1 -4
  276. data/lib/mongo/monitoring/event/topology_opening.rb +1 -4
  277. data/lib/mongo/monitoring/event.rb +0 -1
  278. data/lib/mongo/monitoring/publishable.rb +20 -30
  279. data/lib/mongo/monitoring/sdam_log_subscriber.rb +0 -2
  280. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +0 -3
  281. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +0 -3
  282. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +0 -3
  283. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +5 -8
  284. data/lib/mongo/monitoring/topology_closed_log_subscriber.rb +0 -3
  285. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +0 -3
  286. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +1 -3
  287. data/lib/mongo/monitoring.rb +38 -39
  288. data/lib/mongo/operation/aggregate/op_msg.rb +0 -2
  289. data/lib/mongo/operation/aggregate/result.rb +3 -6
  290. data/lib/mongo/operation/aggregate.rb +0 -2
  291. data/lib/mongo/operation/collections_info/result.rb +0 -3
  292. data/lib/mongo/operation/collections_info.rb +0 -2
  293. data/lib/mongo/operation/command/op_msg.rb +1 -4
  294. data/lib/mongo/operation/command.rb +0 -2
  295. data/lib/mongo/operation/context.rb +13 -16
  296. data/lib/mongo/operation/count/op_msg.rb +2 -4
  297. data/lib/mongo/operation/count.rb +0 -2
  298. data/lib/mongo/operation/create/op_msg.rb +2 -5
  299. data/lib/mongo/operation/create.rb +4 -2
  300. data/lib/mongo/operation/create_index/op_msg.rb +3 -7
  301. data/lib/mongo/operation/create_index.rb +0 -2
  302. data/lib/mongo/operation/create_user/op_msg.rb +2 -4
  303. data/lib/mongo/operation/create_user.rb +0 -2
  304. data/lib/mongo/operation/delete/bulk_result.rb +2 -3
  305. data/lib/mongo/operation/delete/op_msg.rb +3 -10
  306. data/lib/mongo/operation/delete/result.rb +0 -3
  307. data/lib/mongo/operation/delete.rb +1 -5
  308. data/lib/mongo/operation/distinct/op_msg.rb +2 -5
  309. data/lib/mongo/operation/distinct.rb +0 -2
  310. data/lib/mongo/operation/drop/op_msg.rb +0 -2
  311. data/lib/mongo/operation/drop.rb +0 -2
  312. data/lib/mongo/operation/drop_database/op_msg.rb +0 -2
  313. data/lib/mongo/operation/drop_database.rb +0 -2
  314. data/lib/mongo/operation/drop_index/op_msg.rb +4 -6
  315. data/lib/mongo/operation/drop_index.rb +0 -2
  316. data/lib/mongo/operation/explain/op_msg.rb +0 -2
  317. data/lib/mongo/operation/explain/result.rb +0 -3
  318. data/lib/mongo/operation/explain.rb +0 -2
  319. data/lib/mongo/operation/find/builder/command.rb +4 -12
  320. data/lib/mongo/operation/find/builder/flags.rb +9 -15
  321. data/lib/mongo/operation/find/builder/modifiers.rb +1 -4
  322. data/lib/mongo/operation/find/builder.rb +0 -1
  323. data/lib/mongo/operation/find/op_msg.rb +4 -12
  324. data/lib/mongo/operation/find/result.rb +0 -3
  325. data/lib/mongo/operation/find.rb +0 -2
  326. data/lib/mongo/operation/get_more/command_builder.rb +1 -6
  327. data/lib/mongo/operation/get_more/op_msg.rb +10 -4
  328. data/lib/mongo/operation/get_more/result.rb +0 -3
  329. data/lib/mongo/operation/get_more.rb +0 -2
  330. data/lib/mongo/operation/indexes/op_msg.rb +0 -2
  331. data/lib/mongo/operation/indexes/result.rb +1 -5
  332. data/lib/mongo/operation/indexes.rb +0 -2
  333. data/lib/mongo/operation/insert/bulk_result.rb +2 -6
  334. data/lib/mongo/operation/insert/op_msg.rb +7 -6
  335. data/lib/mongo/operation/insert/result.rb +0 -3
  336. data/lib/mongo/operation/insert.rb +2 -5
  337. data/lib/mongo/operation/kill_cursors/command_builder.rb +0 -3
  338. data/lib/mongo/operation/kill_cursors/op_msg.rb +1 -3
  339. data/lib/mongo/operation/kill_cursors.rb +0 -2
  340. data/lib/mongo/operation/list_collections/op_msg.rb +4 -6
  341. data/lib/mongo/operation/list_collections/result.rb +1 -4
  342. data/lib/mongo/operation/list_collections.rb +0 -2
  343. data/lib/mongo/operation/map_reduce/op_msg.rb +0 -2
  344. data/lib/mongo/operation/map_reduce/result.rb +3 -6
  345. data/lib/mongo/operation/map_reduce.rb +0 -2
  346. data/lib/mongo/operation/op_msg_base.rb +0 -1
  347. data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -5
  348. data/lib/mongo/operation/parallel_scan/result.rb +2 -5
  349. data/lib/mongo/operation/parallel_scan.rb +0 -2
  350. data/lib/mongo/operation/remove_user/op_msg.rb +2 -4
  351. data/lib/mongo/operation/remove_user.rb +0 -2
  352. data/lib/mongo/operation/result.rb +38 -48
  353. data/lib/mongo/operation/shared/bypass_document_validation.rb +3 -7
  354. data/lib/mongo/operation/shared/causal_consistency_supported.rb +0 -3
  355. data/lib/mongo/operation/shared/executable.rb +29 -31
  356. data/lib/mongo/operation/shared/executable_no_validate.rb +0 -3
  357. data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -2
  358. data/lib/mongo/operation/shared/idable.rb +3 -6
  359. data/lib/mongo/operation/shared/limited.rb +0 -3
  360. data/lib/mongo/operation/shared/object_id_generator.rb +0 -3
  361. data/lib/mongo/operation/shared/op_msg_executable.rb +0 -2
  362. data/lib/mongo/operation/shared/polymorphic_lookup.rb +0 -2
  363. data/lib/mongo/operation/shared/polymorphic_result.rb +2 -4
  364. data/lib/mongo/operation/shared/read_preference_supported.rb +10 -15
  365. data/lib/mongo/operation/shared/response_handling.rb +13 -26
  366. data/lib/mongo/operation/shared/result/aggregatable.rb +12 -13
  367. data/lib/mongo/operation/shared/sessions_supported.rb +87 -99
  368. data/lib/mongo/operation/shared/specifiable.rb +37 -59
  369. data/lib/mongo/operation/shared/write.rb +12 -17
  370. data/lib/mongo/operation/shared/write_concern_supported.rb +4 -7
  371. data/lib/mongo/operation/update/bulk_result.rb +13 -17
  372. data/lib/mongo/operation/update/op_msg.rb +2 -5
  373. data/lib/mongo/operation/update/result.rb +5 -5
  374. data/lib/mongo/operation/update.rb +1 -5
  375. data/lib/mongo/operation/update_user/op_msg.rb +2 -4
  376. data/lib/mongo/operation/update_user.rb +0 -2
  377. data/lib/mongo/operation/users_info/op_msg.rb +2 -4
  378. data/lib/mongo/operation/users_info/result.rb +1 -4
  379. data/lib/mongo/operation/users_info.rb +0 -2
  380. data/lib/mongo/operation/write_command/op_msg.rb +2 -10
  381. data/lib/mongo/operation/write_command.rb +0 -2
  382. data/lib/mongo/operation.rb +9 -14
  383. data/lib/mongo/options/mapper.rb +8 -15
  384. data/lib/mongo/options/redacted.rb +7 -9
  385. data/lib/mongo/options.rb +0 -1
  386. data/lib/mongo/protocol/bit_vector.rb +3 -5
  387. data/lib/mongo/protocol/caching_hash.rb +2 -7
  388. data/lib/mongo/protocol/compressed.rb +5 -10
  389. data/lib/mongo/protocol/get_more.rb +2 -8
  390. data/lib/mongo/protocol/kill_cursors.rb +2 -8
  391. data/lib/mongo/protocol/message.rb +103 -105
  392. data/lib/mongo/protocol/msg.rb +48 -63
  393. data/lib/mongo/protocol/query.rb +32 -41
  394. data/lib/mongo/protocol/registry.rb +2 -5
  395. data/lib/mongo/protocol/reply.rb +10 -16
  396. data/lib/mongo/protocol/serializers.rb +41 -59
  397. data/lib/mongo/protocol.rb +0 -1
  398. data/lib/mongo/query_cache.rb +7 -15
  399. data/lib/mongo/retryable/backpressure.rb +31 -0
  400. data/lib/mongo/retryable/base_worker.rb +39 -13
  401. data/lib/mongo/retryable/read_worker.rb +77 -21
  402. data/lib/mongo/retryable/retry_policy.rb +59 -0
  403. data/lib/mongo/retryable/write_worker.rb +155 -56
  404. data/lib/mongo/retryable.rb +70 -9
  405. data/lib/mongo/search_index/view.rb +30 -10
  406. data/lib/mongo/semaphore.rb +0 -1
  407. data/lib/mongo/server/app_metadata/environment.rb +3 -3
  408. data/lib/mongo/server/app_metadata/platform.rb +17 -4
  409. data/lib/mongo/server/app_metadata.rb +4 -5
  410. data/lib/mongo/server/connection.rb +79 -61
  411. data/lib/mongo/server/connection_base.rb +43 -53
  412. data/lib/mongo/server/connection_common.rb +41 -64
  413. data/lib/mongo/server/connection_pool/generation_manager.rb +6 -11
  414. data/lib/mongo/server/connection_pool/populator.rb +1 -4
  415. data/lib/mongo/server/connection_pool.rb +195 -167
  416. data/lib/mongo/server/description/features.rb +51 -59
  417. data/lib/mongo/server/description/load_balancer.rb +0 -2
  418. data/lib/mongo/server/description.rb +117 -138
  419. data/lib/mongo/server/monitor/app_metadata.rb +3 -4
  420. data/lib/mongo/server/monitor/connection.rb +28 -35
  421. data/lib/mongo/server/monitor.rb +65 -60
  422. data/lib/mongo/server/pending_connection.rb +70 -71
  423. data/lib/mongo/server/push_monitor/connection.rb +0 -3
  424. data/lib/mongo/server/push_monitor.rb +21 -29
  425. data/lib/mongo/server/round_trip_time_calculator.rb +11 -17
  426. data/lib/mongo/server.rb +62 -94
  427. data/lib/mongo/server_selector/base.rb +133 -157
  428. data/lib/mongo/server_selector/nearest.rb +2 -5
  429. data/lib/mongo/server_selector/primary.rb +1 -5
  430. data/lib/mongo/server_selector/primary_preferred.rb +2 -6
  431. data/lib/mongo/server_selector/secondary.rb +2 -6
  432. data/lib/mongo/server_selector/secondary_preferred.rb +1 -5
  433. data/lib/mongo/server_selector.rb +3 -4
  434. data/lib/mongo/session/server_session.rb +6 -7
  435. data/lib/mongo/session/session_pool.rb +20 -34
  436. data/lib/mongo/session.rb +334 -199
  437. data/lib/mongo/socket/ocsp_cache.rb +8 -13
  438. data/lib/mongo/socket/ocsp_verifier.rb +69 -70
  439. data/lib/mongo/socket/ssl.rb +44 -43
  440. data/lib/mongo/socket/tcp.rb +5 -8
  441. data/lib/mongo/socket/unix.rb +0 -4
  442. data/lib/mongo/socket.rb +80 -102
  443. data/lib/mongo/srv/monitor.rb +10 -11
  444. data/lib/mongo/srv/resolver.rb +15 -24
  445. data/lib/mongo/srv/result.rb +25 -21
  446. data/lib/mongo/srv.rb +0 -1
  447. data/lib/mongo/timeout.rb +4 -11
  448. data/lib/mongo/topology_version.rb +8 -13
  449. data/lib/mongo/tracing/open_telemetry/command_tracer.rb +320 -0
  450. data/lib/mongo/tracing/open_telemetry/operation_tracer.rb +227 -0
  451. data/lib/mongo/tracing/open_telemetry/tracer.rb +236 -0
  452. data/lib/mongo/{error/server_api_not_supported.rb → tracing/open_telemetry.rb} +10 -10
  453. data/lib/mongo/tracing.rb +42 -0
  454. data/lib/mongo/uri/options_mapper.rb +135 -126
  455. data/lib/mongo/uri/srv_protocol.rb +34 -42
  456. data/lib/mongo/uri.rb +95 -139
  457. data/lib/mongo/utils.rb +5 -12
  458. data/lib/mongo/version.rb +1 -1
  459. data/lib/mongo/write_concern/acknowledged.rb +0 -2
  460. data/lib/mongo/write_concern/base.rb +6 -6
  461. data/lib/mongo/write_concern/unacknowledged.rb +0 -2
  462. data/lib/mongo/write_concern.rb +14 -15
  463. data/lib/mongo.rb +4 -3
  464. data/mongo.gemspec +17 -17
  465. metadata +11 -5
  466. data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +0 -32
  467. data/lib/mongo/operation/shared/validatable.rb +0 -87
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:todo all
3
2
 
4
3
  # Copyright (C) 2014-2020 MongoDB Inc.
5
4
  #
@@ -17,7 +16,6 @@
17
16
 
18
17
  module Mongo
19
18
  class Server
20
-
21
19
  # Represents a connection pool for server connections.
22
20
  #
23
21
  # @since 2.0.0, largely rewritten in 2.9.0
@@ -52,7 +50,7 @@ module Mongo
52
50
  # thus anything over 15 seconds is potentially dangerous.
53
51
  #
54
52
  # @since 2.9.0
55
- DEFAULT_WAIT_TIMEOUT = 10.freeze
53
+ DEFAULT_WAIT_TIMEOUT = 10
56
54
 
57
55
  # Condition variable broadcast when the size of the pool changes
58
56
  # to wake up the populator
@@ -100,31 +98,32 @@ module Mongo
100
98
  # @since 2.0.0, API changed in 2.9.0
101
99
 
102
100
  def initialize(server, options = {})
103
- unless server.is_a?(Server)
104
- raise ArgumentError, 'First argument must be a Server instance'
105
- end
101
+ raise ArgumentError, 'First argument must be a Server instance' unless server.is_a?(Server)
102
+
106
103
  options = options.dup
107
104
  if options[:min_size] && options[:min_pool_size] && options[:min_size] != options[:min_pool_size]
108
- raise ArgumentError, "Min size #{options[:min_size]} is not identical to min pool size #{options[:min_pool_size]}"
105
+ raise ArgumentError,
106
+ "Min size #{options[:min_size]} is not identical to min pool size #{options[:min_pool_size]}"
109
107
  end
110
108
  if options[:max_size] && options[:max_pool_size] && options[:max_size] != options[:max_pool_size]
111
- raise ArgumentError, "Max size #{options[:max_size]} is not identical to max pool size #{options[:max_pool_size]}"
109
+ raise ArgumentError,
110
+ "Max size #{options[:max_size]} is not identical to max pool size #{options[:max_pool_size]}"
112
111
  end
113
112
  if options[:wait_timeout] && options[:wait_queue_timeout] && options[:wait_timeout] != options[:wait_queue_timeout]
114
- raise ArgumentError, "Wait timeout #{options[:wait_timeout]} is not identical to wait queue timeout #{options[:wait_queue_timeout]}"
113
+ raise ArgumentError,
114
+ "Wait timeout #{options[:wait_timeout]} is not identical to wait queue timeout #{options[:wait_queue_timeout]}"
115
115
  end
116
+
116
117
  options[:min_size] ||= options[:min_pool_size]
117
118
  options.delete(:min_pool_size)
118
119
  options[:max_size] ||= options[:max_pool_size]
119
120
  options.delete(:max_pool_size)
120
121
  if options[:min_size] && options[:max_size] &&
121
- (options[:max_size] != 0 && options[:min_size] > options[:max_size])
122
- then
122
+ options[:max_size] != 0 && options[:min_size] > options[:max_size]
123
123
  raise ArgumentError, "Cannot have min size #{options[:min_size]} exceed max size #{options[:max_size]}"
124
124
  end
125
- if options[:wait_queue_timeout]
126
- options[:wait_timeout] ||= options[:wait_queue_timeout]
127
- end
125
+
126
+ options[:wait_timeout] ||= options[:wait_queue_timeout] if options[:wait_queue_timeout]
128
127
  options.delete(:wait_queue_timeout)
129
128
 
130
129
  @server = server
@@ -137,7 +136,7 @@ module Mongo
137
136
  # A connection owned by this pool should be either in the
138
137
  # available connections array (which is used as a stack)
139
138
  # or in the checked out connections set.
140
- @available_connections = available_connections = []
139
+ @available_connections = []
141
140
  @checked_out_connections = Set.new
142
141
  @pending_connections = Set.new
143
142
  @interrupt_connections = []
@@ -148,7 +147,7 @@ module Mongo
148
147
  # must do so under this lock.
149
148
  @lock = Mutex.new
150
149
 
151
- # Background thread reponsible for maintaining the size of
150
+ # Background thread responsible for maintaining the size of
152
151
  # the pool to at least min_size
153
152
  @populator = Populator.new(self, options)
154
153
  @populate_semaphore = Semaphore.new
@@ -164,12 +163,13 @@ module Mongo
164
163
  @connection_requests = 0
165
164
 
166
165
  # Condition variable to enforce the second check in check_out: max_connecting.
167
- # Thei condition variable should be signaled when the number of pending
166
+ # This condition variable should be signaled when the number of pending
168
167
  # connections decreases.
169
168
  @max_connecting_cv = Mongo::ConditionVariable.new(@lock)
170
169
  @max_connecting = options.fetch(:max_connecting, DEFAULT_MAX_CONNECTING)
171
170
 
172
- ObjectSpace.define_finalizer(self, self.class.finalize(@available_connections, @pending_connections, @populator))
171
+ ObjectSpace.define_finalizer(self,
172
+ self.class.finalize(@available_connections, @pending_connections, @populator))
173
173
 
174
174
  publish_cmap_event(
175
175
  Monitoring::Event::Cmap::PoolCreated.new(@server.address, options, self)
@@ -191,7 +191,7 @@ module Mongo
191
191
  #
192
192
  # @since 2.9.0
193
193
  def max_size
194
- @max_size ||= options[:max_size] || [DEFAULT_MAX_SIZE, min_size].max
194
+ @max_size ||= options[:max_size] || [ DEFAULT_MAX_SIZE, min_size ].max
195
195
  end
196
196
 
197
197
  # Get the minimum size of the connection pool.
@@ -321,12 +321,12 @@ module Mongo
321
321
  def summary
322
322
  @lock.synchronize do
323
323
  state = if closed?
324
- 'closed'
325
- elsif !@ready
326
- 'paused'
327
- else
328
- 'ready'
329
- end
324
+ 'closed'
325
+ elsif !@ready
326
+ 'paused'
327
+ else
328
+ 'ready'
329
+ end
330
330
  "#<ConnectionPool size=#{unsynchronized_size} (#{min_size}-#{max_size}) " +
331
331
  "used=#{@checked_out_connections.length} avail=#{@available_connections.length} pending=#{@pending_connections.length} #{state}>"
332
332
  end
@@ -378,13 +378,12 @@ module Mongo
378
378
  )
379
379
 
380
380
  publish_cmap_event(
381
- Monitoring::Event::Cmap::ConnectionCheckedOut.new(@server.address, connection.id, self),
381
+ Monitoring::Event::Cmap::ConnectionCheckedOut.new(@server.address, connection.id, self)
382
382
  )
383
383
 
384
- if Lint.enabled?
385
- unless connection.connected?
386
- raise Error::LintError, "Connection pool for #{address} checked out a disconnected connection #{connection.generation}:#{connection.id}"
387
- end
384
+ if Lint.enabled? && !connection.connected?
385
+ raise Error::LintError,
386
+ "Connection pool for #{address} checked out a disconnected connection #{connection.generation}:#{connection.id}"
388
387
  end
389
388
 
390
389
  connection
@@ -392,6 +391,23 @@ module Mongo
392
391
  check_invariants
393
392
  end
394
393
 
394
+ # Returns a pinned connection that is already checked out, if one
395
+ # exists with the given global id. Returns nil otherwise.
396
+ #
397
+ # @param [ Integer ] connection_global_id The global id of the pinned
398
+ # connection.
399
+ #
400
+ # @return [ Connection | nil ] The pinned connection, or nil.
401
+ #
402
+ # @api private
403
+ def check_out_pinned_connection(connection_global_id)
404
+ @lock.synchronize do
405
+ @checked_out_connections.detect do |conn|
406
+ conn.global_id == connection_global_id && conn.pinned?
407
+ end
408
+ end
409
+ end
410
+
395
411
  # Check a connection back into the pool.
396
412
  #
397
413
  # The connection must have been previously created by this pool.
@@ -420,14 +436,16 @@ module Mongo
420
436
  return if connection.closed? && connection.interrupted?
421
437
 
422
438
  unless connection.connection_pool == self
423
- 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})"
439
+ raise ArgumentError,
440
+ "Trying to check in a connection which was not checked out by this pool: #{connection} checked out from pool #{connection.connection_pool} (for #{self})"
424
441
  end
425
442
 
426
443
  unless @checked_out_connections.include?(connection)
427
- raise ArgumentError, "Trying to check in a connection which is not currently checked out by this pool: #{connection} (for #{self})"
444
+ raise ArgumentError,
445
+ "Trying to check in a connection which is not currently checked out by this pool: #{connection} (for #{self})"
428
446
  end
429
447
 
430
- # Note: if an event handler raises, resource will not be signaled.
448
+ # NOTE: if an event handler raises, resource will not be signaled.
431
449
  # This means threads waiting for a connection to free up when
432
450
  # the pool is at max size may time out.
433
451
  # Threads that begin waiting after this method completes (with
@@ -495,7 +513,7 @@ module Mongo
495
513
  raise Error::LintError, "Attempting to pause pool for server #{@server.summary} which is known"
496
514
  end
497
515
 
498
- return if !@ready
516
+ return unless @ready
499
517
 
500
518
  @ready = false
501
519
  end
@@ -551,9 +569,7 @@ module Mongo
551
569
  # Generation must be bumped before emitting pool cleared event.
552
570
  @generation_manager.bump(service_id: service_id)
553
571
 
554
- unless options && options[:lazy]
555
- close_available_connections(service_id)
556
- end
572
+ close_available_connections(service_id) unless options && options[:lazy]
557
573
 
558
574
  if options && options[:interrupt_in_use_connections]
559
575
  schedule_for_interruption(@checked_out_connections, service_id)
@@ -618,12 +634,12 @@ module Mongo
618
634
  Monitoring::Event::Cmap::PoolReady.new(@server.address, options, self)
619
635
  )
620
636
 
621
- if options.fetch(:populator_io, true)
622
- if @populator.running?
623
- @populate_semaphore.signal
624
- else
625
- @populator.run!
626
- end
637
+ return unless options.fetch(:populator_io, true)
638
+
639
+ if @populator.running?
640
+ @populate_semaphore.signal
641
+ else
642
+ @populator.run!
627
643
  end
628
644
  end
629
645
 
@@ -715,16 +731,35 @@ module Mongo
715
731
  def with_connection(connection_global_id: nil, context: nil)
716
732
  raise_if_closed!
717
733
 
718
- connection = check_out(
734
+ # If a specific connection is requested and it is already checked out
735
+ # and pinned (e.g. for a transaction or cursor in load-balanced mode),
736
+ # reuse it directly without going through the check_out/check_in cycle.
737
+ if connection_global_id
738
+ connection = @lock.synchronize do
739
+ @checked_out_connections.detect do |conn|
740
+ conn.global_id == connection_global_id && conn.pinned?
741
+ end
742
+ end
743
+ end
744
+
745
+ connection ||= check_out(
719
746
  connection_global_id: connection_global_id,
720
747
  context: context
721
748
  )
749
+
722
750
  yield(connection)
723
751
  rescue Error::SocketError, Error::SocketTimeoutError, Error::ConnectionPerished => e
724
752
  maybe_raise_pool_cleared!(connection, e)
725
753
  ensure
726
- if connection
727
- check_in(connection)
754
+ if connection && !connection.pinned?
755
+ # Do not check in if the connection is pinned (the session or cursor
756
+ # owns it and will check it in later when unpinning). Also skip
757
+ # check-in if the connection was already checked in during the block
758
+ # (e.g. by Session#unpin after an error on the first operation).
759
+ checked_out = @lock.synchronize do
760
+ @checked_out_connections.include?(connection)
761
+ end
762
+ check_in(connection) if checked_out
728
763
  end
729
764
  end
730
765
 
@@ -740,13 +775,11 @@ module Mongo
740
775
  i = 0
741
776
  while i < @available_connections.length
742
777
  connection = @available_connections[i]
743
- if last_checkin = connection.last_checkin
744
- if (Time.now - last_checkin) > max_idle_time
745
- connection.disconnect!(reason: :idle)
746
- @available_connections.delete_at(i)
747
- @populate_semaphore.signal
748
- next
749
- end
778
+ if (last_checkin = connection.last_checkin) && ((Time.now - last_checkin) > max_idle_time)
779
+ connection.disconnect!(reason: :idle)
780
+ @available_connections.delete_at(i)
781
+ @populate_semaphore.signal
782
+ next
750
783
  end
751
784
  i += 1
752
785
  end
@@ -787,7 +820,7 @@ module Mongo
787
820
  # @return [ true | false ] Whether this method should be called again
788
821
  # to create more connections.
789
822
  # @raise [ Error::AuthError, Error ] The second socket-related error raised if a retry
790
- # occured, or the non socket-related error
823
+ # occurred, or the non socket-related error
791
824
  #
792
825
  # @api private
793
826
  def populate
@@ -801,7 +834,7 @@ module Mongo
801
834
  log_warn("Populator failed to connect a connection for #{address}: #{e.class}: #{e}. It will retry.")
802
835
  end
803
836
 
804
- return create_and_add_connection
837
+ create_and_add_connection
805
838
  end
806
839
 
807
840
  # Finalize the connection pool for garbage collection.
@@ -811,7 +844,7 @@ module Mongo
811
844
  # @param [ Populator ] populator The populator.
812
845
  #
813
846
  # @return [ Proc ] The Finalizer.
814
- def self.finalize(available_connections, pending_connections, populator)
847
+ def self.finalize(available_connections, pending_connections, _populator)
815
848
  proc do
816
849
  available_connections.each do |connection|
817
850
  connection.disconnect!(reason: :pool_closed)
@@ -841,9 +874,7 @@ module Mongo
841
874
  conn = @available_connections.detect do |conn|
842
875
  conn.global_id == connection_global_id
843
876
  end
844
- if conn
845
- @available_connections.delete(conn)
846
- end
877
+ @available_connections.delete(conn) if conn
847
878
  conn
848
879
  else
849
880
  @available_connections.pop
@@ -851,16 +882,14 @@ module Mongo
851
882
  end
852
883
 
853
884
  def create_connection
854
- r, _ = @generation_manager.pipe_fds(service_id: server.description.service_id)
885
+ r, = @generation_manager.pipe_fds(service_id: server.description.service_id)
855
886
  opts = options.merge(
856
887
  connection_pool: self,
857
888
  pipe: r
858
889
  # Do not pass app metadata - this will be retrieved by the connection
859
890
  # based on the auth needs.
860
891
  )
861
- unless @server.load_balancer?
862
- opts[:generation] = generation
863
- end
892
+ opts[:generation] = generation unless @server.load_balancer?
864
893
  Connection.new(@server, opts)
865
894
  end
866
895
 
@@ -875,14 +904,14 @@ module Mongo
875
904
 
876
905
  @lock.synchronize do
877
906
  if !closed? && @ready &&
878
- (unsynchronized_size + @connection_requests) < min_size &&
879
- @pending_connections.length < @max_connecting
880
- then
907
+ (unsynchronized_size + @connection_requests) < min_size &&
908
+ @pending_connections.length < @max_connecting
881
909
  connection = create_connection
882
910
  @pending_connections << connection
883
911
  else
884
912
  return true if remove_interrupted_connections
885
913
  return true if remove_stale_connection
914
+
886
915
  return false
887
916
  end
888
917
  end
@@ -910,11 +939,11 @@ module Mongo
910
939
 
911
940
  # Removes and disconnects all stale available connections.
912
941
  def remove_stale_connection
913
- if conn = @available_connections.detect(&method(:connection_stale_unlocked?))
914
- conn.disconnect!(reason: :stale)
915
- @available_connections.delete(conn)
916
- return true
917
- end
942
+ return unless conn = @available_connections.detect { |c| connection_stale_unlocked?(c) }
943
+
944
+ conn.disconnect!(reason: :stale)
945
+ @available_connections.delete(conn)
946
+ true
918
947
  end
919
948
 
920
949
  # Interrupt connections scheduled for interruption.
@@ -957,7 +986,7 @@ module Mongo
957
986
  # @return [ true | false ] Whether the connection is stale.
958
987
  def connection_stale_unlocked?(connection)
959
988
  connection.generation != generation_unlocked(service_id: connection.service_id) &&
960
- !connection.pinned?
989
+ !connection.pinned?
961
990
  end
962
991
 
963
992
  # Asserts that the pool has not been closed.
@@ -966,9 +995,9 @@ module Mongo
966
995
  #
967
996
  # @since 2.9.0
968
997
  def raise_if_closed!
969
- if closed?
970
- raise Error::PoolClosedError.new(@server.address, self)
971
- end
998
+ return unless closed?
999
+
1000
+ raise Error::PoolClosedError.new(@server.address, self)
972
1001
  end
973
1002
 
974
1003
  # If the connection was interrupted, raise a pool cleared error. If it
@@ -980,31 +1009,36 @@ module Mongo
980
1009
  # @raise [ Mongo::Error | Mongo::Error::PoolClearedError ] A PoolClearedError
981
1010
  # if the connection was interrupted, the original error if not.
982
1011
  def maybe_raise_pool_cleared!(connection, e)
983
- if connection&.interrupted?
984
- err = Error::PoolClearedError.new(connection.server.address, connection.server.pool_internal).tap do |err|
985
- e.labels.each { |l| err.add_label(l) }
986
- end
987
- raise err
988
- else
989
- raise e
1012
+ raise e unless connection&.interrupted?
1013
+
1014
+ err = Error::PoolClearedError.new(connection.server.address, connection.server.pool_internal).tap do |err|
1015
+ e.labels.each { |l| err.add_label(l) }
990
1016
  end
1017
+ raise err
991
1018
  end
992
1019
 
993
1020
  # Attempts to connect (handshake and auth) the connection. If an error is
994
1021
  # encountered, closes the connection and raises the error.
995
1022
  def connect_connection(connection, context = nil)
996
- begin
997
- connection.connect!(context)
998
- rescue Exception
999
- connection.disconnect!(reason: :error)
1000
- raise
1023
+ connection.connect!(context)
1024
+ rescue Exception => e
1025
+ # When a connection encounters an error during creation
1026
+ # (including handshake and authentication), mark the server
1027
+ # as Unknown so the pool is cleared (per CMAP spec).
1028
+ # The unknown! call must happen before disconnect! so that
1029
+ # the ConnectionPoolCleared event is published before the
1030
+ # ConnectionClosed event.
1031
+ # Errors with the SystemOverloadedError label (network errors
1032
+ # during handshake) are excluded per the SDAM spec — those
1033
+ # must not change the server description.
1034
+ if e.is_a?(Mongo::Error) && !e.label?('SystemOverloadedError')
1035
+ @server.unknown!(
1036
+ generation: e.generation,
1037
+ service_id: e.service_id,
1038
+ stop_push_monitor: true
1039
+ )
1001
1040
  end
1002
- rescue Error::SocketError, Error::SocketTimeoutError => exc
1003
- @server.unknown!(
1004
- generation: exc.generation,
1005
- service_id: exc.service_id,
1006
- stop_push_monitor: true,
1007
- )
1041
+ connection.disconnect!(reason: :error)
1008
1042
  raise
1009
1043
  end
1010
1044
 
@@ -1039,15 +1073,13 @@ module Mongo
1039
1073
  loop do
1040
1074
  conn = @available_connections.detect do |conn|
1041
1075
  conn.service_id == service_id &&
1042
- conn.generation < @generation_manager.generation(service_id: service_id)
1043
- end
1044
- if conn
1045
- @available_connections.delete(conn)
1046
- conn.disconnect!(reason: :stale, interrupted: true)
1047
- @populate_semaphore.signal
1048
- else
1049
- break
1076
+ conn.generation < @generation_manager.generation(service_id: service_id)
1050
1077
  end
1078
+ break unless conn
1079
+
1080
+ @available_connections.delete(conn)
1081
+ conn.disconnect!(reason: :stale, interrupted: true)
1082
+ @populate_semaphore.signal
1051
1083
  end
1052
1084
  else
1053
1085
  @available_connections.delete_if do |conn|
@@ -1067,7 +1099,7 @@ module Mongo
1067
1099
  def schedule_for_interruption(connections, service_id)
1068
1100
  @interrupt_connections += connections.select do |conn|
1069
1101
  (!server.load_balancer? || conn.service_id == service_id) &&
1070
- conn.generation < @generation_manager.generation(service_id: service_id)
1102
+ conn.generation < @generation_manager.generation(service_id: service_id)
1071
1103
  end
1072
1104
  end
1073
1105
 
@@ -1087,23 +1119,23 @@ module Mongo
1087
1119
  publish_cmap_event(
1088
1120
  Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1089
1121
  @server.address,
1090
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::TIMEOUT,
1091
- ),
1122
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::TIMEOUT
1123
+ )
1092
1124
  )
1093
1125
 
1094
1126
  connection_global_id_msg = if connection_global_id
1095
- " for connection #{connection_global_id}"
1096
- else
1097
- ''
1098
- end
1099
-
1100
- msg = "Timed out attempting to check out a connection " +
1101
- "from pool for #{@server.address}#{connection_global_id_msg} after #{wait_timeout} sec. " +
1102
- "Connections in pool: #{@available_connections.length} available, " +
1103
- "#{@checked_out_connections.length} checked out, " +
1104
- "#{@pending_connections.length} pending, " +
1105
- "#{@connection_requests} connections requests " +
1106
- "(max size: #{max_size})"
1127
+ " for connection #{connection_global_id}"
1128
+ else
1129
+ ''
1130
+ end
1131
+
1132
+ msg = 'Timed out attempting to check out a connection ' +
1133
+ "from pool for #{@server.address}#{connection_global_id_msg} after #{wait_timeout} sec. " +
1134
+ "Connections in pool: #{@available_connections.length} available, " +
1135
+ "#{@checked_out_connections.length} checked out, " +
1136
+ "#{@pending_connections.length} pending, " +
1137
+ "#{@connection_requests} connections requests " +
1138
+ "(max size: #{max_size})"
1107
1139
  raise Error::ConnectionCheckOutTimeout.new(msg, address: @server.address)
1108
1140
  end
1109
1141
 
@@ -1114,31 +1146,31 @@ module Mongo
1114
1146
  end
1115
1147
 
1116
1148
  def raise_if_pool_closed!
1117
- if closed?
1118
- publish_cmap_event(
1119
- Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1120
- @server.address,
1121
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::POOL_CLOSED
1122
- ),
1149
+ return unless closed?
1150
+
1151
+ publish_cmap_event(
1152
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1153
+ @server.address,
1154
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::POOL_CLOSED
1123
1155
  )
1124
- raise Error::PoolClosedError.new(@server.address, self)
1125
- end
1156
+ )
1157
+ raise Error::PoolClosedError.new(@server.address, self)
1126
1158
  end
1127
1159
 
1128
1160
  def raise_if_pool_paused!
1129
1161
  raise_unless_locked!
1130
1162
 
1131
- if !@ready
1132
- publish_cmap_event(
1133
- Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1134
- @server.address,
1135
- # CMAP spec decided to conflate pool paused with all the other
1136
- # possible non-timeout errors.
1137
- Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR,
1138
- ),
1163
+ return if @ready
1164
+
1165
+ publish_cmap_event(
1166
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1167
+ @server.address,
1168
+ # CMAP spec decided to conflate pool paused with all the other
1169
+ # possible non-timeout errors.
1170
+ Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
1139
1171
  )
1140
- raise Error::PoolPausedError.new(@server.address, self)
1141
- end
1172
+ )
1173
+ raise Error::PoolPausedError.new(@server.address, self)
1142
1174
  end
1143
1175
 
1144
1176
  def raise_if_pool_paused_locked!
@@ -1155,12 +1187,12 @@ module Mongo
1155
1187
  end
1156
1188
 
1157
1189
  def raise_unless_locked!
1158
- unless @lock.owned?
1159
- raise ArgumentError, "the lock must be owned when calling this method"
1160
- end
1190
+ return if @lock.owned?
1191
+
1192
+ raise ArgumentError, 'the lock must be owned when calling this method'
1161
1193
  end
1162
1194
 
1163
- def valid_available_connection?(connection, pid, connection_global_id)
1195
+ def valid_available_connection?(connection, pid, _connection_global_id)
1164
1196
  if connection.pid != pid
1165
1197
  log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{connection.pid}, new pid #{pid}")
1166
1198
  connection.disconnect!(reason: :stale)
@@ -1168,7 +1200,7 @@ module Mongo
1168
1200
  return false
1169
1201
  end
1170
1202
 
1171
- if !connection.pinned?
1203
+ unless connection.pinned?
1172
1204
  # If connection is marked as pinned, it is used by a transaction
1173
1205
  # or a series of cursor operations in a load balanced setup.
1174
1206
  # In this case connection should not be disconnected until
@@ -1184,8 +1216,7 @@ module Mongo
1184
1216
  end
1185
1217
 
1186
1218
  if max_idle_time && connection.last_checkin &&
1187
- Time.now - connection.last_checkin > max_idle_time
1188
- then
1219
+ Time.now - connection.last_checkin > max_idle_time
1189
1220
  connection.disconnect!(reason: :idle)
1190
1221
  @populate_semaphore.signal
1191
1222
  return false
@@ -1209,9 +1240,7 @@ module Mongo
1209
1240
  # and remains so for longer than the wait timeout.
1210
1241
  def get_connection(pid, connection_global_id)
1211
1242
  if connection = next_available_connection(connection_global_id)
1212
- unless valid_available_connection?(connection, pid, connection_global_id)
1213
- return nil
1214
- end
1243
+ return nil unless valid_available_connection?(connection, pid, connection_global_id)
1215
1244
 
1216
1245
  # We've got a connection, so we decrement the number of connection
1217
1246
  # requests.
@@ -1222,13 +1251,11 @@ module Mongo
1222
1251
  # If the connection is connected, it's not considered a
1223
1252
  # "pending connection". The pending_connections list represents
1224
1253
  # the set of connections that are awaiting connection.
1225
- unless connection.connected?
1226
- @pending_connections << connection
1227
- end
1228
- return connection
1254
+ @pending_connections << connection unless connection.connected?
1255
+ connection
1229
1256
  elsif connection_global_id && @server.load_balancer?
1230
1257
  # A particular connection is requested, but it is not available.
1231
- # If it is nether available not checked out, we should stop here.
1258
+ # If it is neither available nor checked out, we should stop here.
1232
1259
  @checked_out_connections.detect do |conn|
1233
1260
  conn.global_id == connection_global_id
1234
1261
  end.tap do |conn|
@@ -1237,7 +1264,7 @@ module Mongo
1237
1264
  Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1238
1265
  @server.address,
1239
1266
  Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
1240
- ),
1267
+ )
1241
1268
  )
1242
1269
  # We're going to raise, so we need to decrement the number of
1243
1270
  # connection requests.
@@ -1253,7 +1280,7 @@ module Mongo
1253
1280
  connection = create_connection
1254
1281
  @connection_requests -= 1
1255
1282
  @pending_connections << connection
1256
- return connection
1283
+ connection
1257
1284
  end
1258
1285
  end
1259
1286
 
@@ -1269,7 +1296,7 @@ module Mongo
1269
1296
  # @raise [ Error::PoolClosedError ] If the pool has been closed.
1270
1297
  # @raise [ Timeout::Error ] If the connection pool is at maximum size
1271
1298
  # and remains so for longer than the wait timeout.
1272
- def retrieve_and_connect_connection(connection_global_id, context = nil)
1299
+ def retrieve_and_connect_connection(connection_global_id, context = nil)
1273
1300
  deadline = Utils.monotonic_time + wait_timeout(context)
1274
1301
  connection = nil
1275
1302
 
@@ -1290,15 +1317,19 @@ module Mongo
1290
1317
 
1291
1318
  @lock.synchronize do
1292
1319
  @checked_out_connections << connection
1293
- if @pending_connections.include?(connection)
1294
- @pending_connections.delete(connection)
1295
- end
1320
+ @pending_connections.delete(connection) if @pending_connections.include?(connection)
1296
1321
  @max_connecting_cv.signal
1297
1322
  # no need to signal size_cv here since the number of unavailable
1298
1323
  # connections is unchanged.
1299
1324
  end
1300
1325
 
1301
1326
  connection
1327
+ rescue Error::ConnectionCheckOutTimeout
1328
+ # Per the CSOT spec, if a connection checkout fails because the CSOT
1329
+ # deadline expired (rather than a configured waitQueueTimeout), the
1330
+ # error must be a CSOT TimeoutError so that callers can distinguish it.
1331
+ context&.check_timeout!
1332
+ raise
1302
1333
  end
1303
1334
 
1304
1335
  # Waits for a connection to become available, or raises is no connection
@@ -1330,13 +1361,13 @@ module Mongo
1330
1361
 
1331
1362
  connection = get_connection(Process.pid, connection_global_id)
1332
1363
  wait = deadline - Utils.monotonic_time
1333
- if connection.nil? && wait <= 0
1334
- # connection is nil here, it means that get_connection method
1335
- # did not create a new connection; therefore, it did not decrease
1336
- # the connection_requests counter. We need to do it here.
1337
- decrement_connection_requests_and_signal
1338
- raise_check_out_timeout!(connection_global_id)
1339
- end
1364
+ next unless connection.nil? && wait <= 0
1365
+
1366
+ # connection is nil here, it means that get_connection method
1367
+ # did not create a new connection; therefore, it did not decrease
1368
+ # the connection_requests counter. We need to do it here.
1369
+ decrement_connection_requests_and_signal
1370
+ raise_check_out_timeout!(connection_global_id)
1340
1371
  end
1341
1372
 
1342
1373
  connection
@@ -1351,9 +1382,7 @@ module Mongo
1351
1382
  rescue Exception
1352
1383
  # Handshake or authentication failed
1353
1384
  @lock.synchronize do
1354
- if @pending_connections.include?(connection)
1355
- @pending_connections.delete(connection)
1356
- end
1385
+ @pending_connections.delete(connection) if @pending_connections.include?(connection)
1357
1386
  @max_connecting_cv.signal
1358
1387
  @size_cv.signal
1359
1388
  end
@@ -1362,12 +1391,11 @@ module Mongo
1362
1391
  Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
1363
1392
  @server.address,
1364
1393
  Monitoring::Event::Cmap::ConnectionCheckOutFailed::CONNECTION_ERROR
1365
- ),
1394
+ )
1366
1395
  )
1367
1396
  raise
1368
1397
  end
1369
1398
 
1370
-
1371
1399
  # Decrement connection requests counter and signal the condition
1372
1400
  # variables that the number of unavailable connections has decreased.
1373
1401
  def decrement_connection_requests_and_signal