mongo 2.20.1 → 2.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (246) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/Rakefile +2 -2
  4. data/lib/mongo/address.rb +22 -3
  5. data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
  6. data/lib/mongo/auth/base.rb +1 -1
  7. data/lib/mongo/bulk_write.rb +35 -2
  8. data/lib/mongo/client.rb +38 -6
  9. data/lib/mongo/client_encryption.rb +6 -3
  10. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
  11. data/lib/mongo/cluster/sdam_flow.rb +20 -7
  12. data/lib/mongo/cluster.rb +14 -4
  13. data/lib/mongo/collection/helpers.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
  15. data/lib/mongo/collection/view/aggregation.rb +33 -99
  16. data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
  17. data/lib/mongo/collection/view/change_stream.rb +80 -27
  18. data/lib/mongo/collection/view/iterable.rb +76 -60
  19. data/lib/mongo/collection/view/map_reduce.rb +25 -8
  20. data/lib/mongo/collection/view/readable.rb +79 -30
  21. data/lib/mongo/collection/view/writable.rb +109 -48
  22. data/lib/mongo/collection/view.rb +43 -3
  23. data/lib/mongo/collection.rb +158 -23
  24. data/lib/mongo/crypt/auto_encrypter.rb +4 -6
  25. data/lib/mongo/crypt/binding.rb +4 -4
  26. data/lib/mongo/crypt/context.rb +20 -14
  27. data/lib/mongo/crypt/encryption_io.rb +56 -26
  28. data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
  29. data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
  30. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
  31. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
  32. data/lib/mongo/csot_timeout_holder.rb +119 -0
  33. data/lib/mongo/cursor/kill_spec.rb +5 -2
  34. data/lib/mongo/cursor/nontailable.rb +27 -0
  35. data/lib/mongo/cursor.rb +86 -24
  36. data/lib/mongo/cursor_host.rb +82 -0
  37. data/lib/mongo/database/view.rb +81 -14
  38. data/lib/mongo/database.rb +88 -18
  39. data/lib/mongo/error/operation_failure.rb +209 -204
  40. data/lib/mongo/error/server_timeout_error.rb +12 -0
  41. data/lib/mongo/error/socket_timeout_error.rb +3 -1
  42. data/lib/mongo/error/timeout_error.rb +23 -0
  43. data/lib/mongo/error.rb +2 -0
  44. data/lib/mongo/grid/fs_bucket.rb +45 -12
  45. data/lib/mongo/grid/stream/read.rb +15 -1
  46. data/lib/mongo/grid/stream/write.rb +21 -4
  47. data/lib/mongo/index/view.rb +77 -16
  48. data/lib/mongo/operation/context.rb +40 -2
  49. data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
  50. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  51. data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
  52. data/lib/mongo/operation/find/op_msg.rb +45 -0
  53. data/lib/mongo/operation/get_more/op_msg.rb +33 -0
  54. data/lib/mongo/operation/insert/op_msg.rb +3 -2
  55. data/lib/mongo/operation/insert/result.rb +4 -2
  56. data/lib/mongo/operation/list_collections/result.rb +1 -1
  57. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  58. data/lib/mongo/operation/op_msg_base.rb +3 -1
  59. data/lib/mongo/operation/result.rb +26 -5
  60. data/lib/mongo/operation/shared/executable.rb +12 -1
  61. data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
  62. data/lib/mongo/operation/shared/response_handling.rb +3 -3
  63. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  64. data/lib/mongo/operation/shared/timed.rb +52 -0
  65. data/lib/mongo/operation/shared/write.rb +4 -1
  66. data/lib/mongo/operation/update/op_msg.rb +2 -1
  67. data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
  68. data/lib/mongo/operation.rb +1 -0
  69. data/lib/mongo/protocol/message.rb +1 -4
  70. data/lib/mongo/protocol/msg.rb +2 -2
  71. data/lib/mongo/retryable/read_worker.rb +69 -29
  72. data/lib/mongo/retryable/write_worker.rb +49 -18
  73. data/lib/mongo/retryable.rb +8 -2
  74. data/lib/mongo/server/connection.rb +11 -5
  75. data/lib/mongo/server/connection_base.rb +22 -2
  76. data/lib/mongo/server/connection_pool.rb +32 -14
  77. data/lib/mongo/server/description/features.rb +1 -1
  78. data/lib/mongo/server/description.rb +18 -5
  79. data/lib/mongo/server/monitor.rb +7 -4
  80. data/lib/mongo/server/pending_connection.rb +7 -3
  81. data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
  82. data/lib/mongo/server.rb +11 -6
  83. data/lib/mongo/server_selector/base.rb +25 -9
  84. data/lib/mongo/session.rb +78 -9
  85. data/lib/mongo/socket/ssl.rb +109 -17
  86. data/lib/mongo/socket/tcp.rb +40 -6
  87. data/lib/mongo/socket.rb +154 -25
  88. data/lib/mongo/uri/options_mapper.rb +1 -0
  89. data/lib/mongo/version.rb +1 -1
  90. data/lib/mongo.rb +1 -0
  91. data/spec/atlas/atlas_connectivity_spec.rb +4 -0
  92. data/spec/atlas/operations_spec.rb +4 -0
  93. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
  94. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
  95. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
  96. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
  97. data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
  98. data/spec/integration/connection_pool_populator_spec.rb +2 -0
  99. data/spec/integration/cursor_pinning_spec.rb +15 -60
  100. data/spec/integration/cursor_reaping_spec.rb +1 -1
  101. data/spec/integration/docs_examples_spec.rb +1 -1
  102. data/spec/integration/operation_failure_code_spec.rb +1 -1
  103. data/spec/integration/operation_failure_message_spec.rb +3 -3
  104. data/spec/integration/retryable_errors_spec.rb +2 -2
  105. data/spec/integration/sdam_error_handling_spec.rb +2 -1
  106. data/spec/integration/search_indexes_prose_spec.rb +4 -0
  107. data/spec/integration/server_spec.rb +4 -3
  108. data/spec/integration/transactions_api_examples_spec.rb +2 -0
  109. data/spec/kerberos/kerberos_spec.rb +4 -0
  110. data/spec/lite_spec_helper.rb +3 -1
  111. data/spec/mongo/auth/user/view_spec.rb +1 -1
  112. data/spec/mongo/caching_cursor_spec.rb +1 -1
  113. data/spec/mongo/client_encryption_spec.rb +1 -0
  114. data/spec/mongo/client_spec.rb +158 -4
  115. data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
  116. data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
  117. data/spec/mongo/collection_spec.rb +5 -6
  118. data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
  119. data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
  120. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
  121. data/spec/mongo/crypt/handle_spec.rb +1 -1
  122. data/spec/mongo/cursor_spec.rb +26 -9
  123. data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
  124. data/spec/mongo/operation/context_spec.rb +79 -0
  125. data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
  126. data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
  127. data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
  128. data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
  129. data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
  130. data/spec/mongo/operation/shared/csot/examples.rb +113 -0
  131. data/spec/mongo/query_cache_spec.rb +243 -225
  132. data/spec/mongo/retryable_spec.rb +1 -0
  133. data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
  134. data/spec/mongo/socket/ssl_spec.rb +0 -10
  135. data/spec/runners/change_streams/test.rb +2 -2
  136. data/spec/runners/crud/operation.rb +1 -1
  137. data/spec/runners/crud/verifier.rb +3 -1
  138. data/spec/runners/transactions/operation.rb +4 -6
  139. data/spec/runners/unified/ambiguous_operations.rb +13 -0
  140. data/spec/runners/unified/assertions.rb +4 -0
  141. data/spec/runners/unified/change_stream_operations.rb +14 -24
  142. data/spec/runners/unified/crud_operations.rb +82 -59
  143. data/spec/runners/unified/ddl_operations.rb +38 -7
  144. data/spec/runners/unified/grid_fs_operations.rb +37 -2
  145. data/spec/runners/unified/support_operations.rb +43 -4
  146. data/spec/runners/unified/test.rb +22 -10
  147. data/spec/runners/unified.rb +1 -1
  148. data/spec/solo/clean_exit_spec.rb +2 -0
  149. data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
  150. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
  151. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
  152. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
  153. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  154. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
  155. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
  156. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
  157. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
  158. data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
  159. data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
  160. data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
  161. data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
  162. data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
  163. data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
  164. data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
  165. data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
  166. data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
  167. data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
  168. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
  169. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
  170. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
  171. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
  172. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
  173. data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
  174. data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
  175. data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
  176. data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
  177. data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
  178. data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
  179. data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
  180. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
  181. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
  182. data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
  183. data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
  184. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
  185. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
  186. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
  187. data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
  188. data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
  189. data/spec/support/certificates/atlas-ocsp.crt +107 -107
  190. data/spec/support/cluster_tools.rb +3 -3
  191. data/spec/support/common_shortcuts.rb +2 -2
  192. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
  193. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
  194. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
  195. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
  196. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
  197. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
  198. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
  199. data/spec/support/shared/session.rb +2 -2
  200. data/spec/support/spec_setup.rb +2 -2
  201. data/spec/support/utils.rb +3 -1
  202. metadata +78 -91
  203. data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
  204. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
  205. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
  206. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
  207. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
  208. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
  209. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
  210. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
  211. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
  212. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
  213. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
  214. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
  215. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
  216. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
  217. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
  218. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
  219. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
  220. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
  221. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
  222. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
  223. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
  224. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
  225. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
  226. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
  227. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
  228. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
  229. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
  230. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
  231. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
  232. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
  233. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
  234. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
  235. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
  236. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
  237. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
  238. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
  239. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
  240. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
  241. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
  242. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
  243. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
  244. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
  245. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
  246. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a641cd6128fd246b0ac9999f00167631548206573a22989968f2a7a132bc0ae
4
- data.tar.gz: d5526d1ca34219ac644191f1e2c7177877c70063cc5a97992379e8e86065d0ca
3
+ metadata.gz: 5e7f3e9918313d274cc9e065268b75d760d24491b959f7b04cdad49dd0ff38f4
4
+ data.tar.gz: 5071ce689f3c0027ce39c93cd662b355235a2b1728f6308c716eecbaa7b55420
5
5
  SHA512:
6
- metadata.gz: 4c23fd9abff5c29517b2cf0c0094bedfbbe667a96f2494b36e6465d8bbfbe113cd08f05e72d15b6db17ef35a211c4aaa040c20dc99eb65417c3c3690b7712c59
7
- data.tar.gz: 54ffbc332168455337aa4de863db0ca179084a35c271e9f21dbfe2425556bd00e02b2fd46a5c2581aa15d5e9a11b84d9a0c231889774adb129f2ad38b997f4f4
6
+ metadata.gz: d8c716a1754d4d2c704a3dd8ed6fcdc5815a0818168598fbe885886f6962f07182333ce8a68ada32cf0bd5d4664d102c301d97e611bac5a126201b6c3e986597
7
+ data.tar.gz: 1365727e6aa93fa15ab46c058f6d3d553a16e8f06b400f915f37c326f9a3393cbf90c6a585a37c8e9a5b9f8e625fcf8443adc487bb0b29b617ffdf71c9991b75
data/README.md CHANGED
@@ -53,6 +53,9 @@ API documentation for the most recent release can be found
53
53
  To build API documentation for the master branch, check out the
54
54
  repository locally and run `rake docs`.
55
55
 
56
+ High-level driver documentation including tutorials and the reference that were in the docs folder can now be found
57
+ at the docs-ruby repository, [here](https://github.com/mongodb/docs-ruby)
58
+
56
59
  ## Support
57
60
 
58
61
  Commercial support for the driver is available through the
data/Rakefile CHANGED
@@ -21,12 +21,12 @@ CLASSIFIERS = [
21
21
  [%r,^spec_tests,, :spec],
22
22
  ]
23
23
 
24
- RUN_PRIORITY = %i(
24
+ RUN_PRIORITY = (ENV['RUN_PRIORITY'] || %(
25
25
  tx_examples
26
26
  unit unit_server
27
27
  integration sdam_integration cursor_reaping query_cache
28
28
  spec spec_sdam_integration
29
- )
29
+ )).split.map(&:to_sym)
30
30
 
31
31
  RSpec::Core::RakeTask.new(:spec) do |t|
32
32
  #t.rspec_opts = "--profile 5" if ENV['CI']
data/lib/mongo/address.rb CHANGED
@@ -178,6 +178,9 @@ module Mongo
178
178
  # @param [ Hash ] opts The options.
179
179
  #
180
180
  # @option opts [ Float ] :connect_timeout Connect timeout.
181
+ # @option opts [ Boolean ] :csot Whether the client-side operation timeout
182
+ # should be considered when connecting the socket. This option influences
183
+ # only what errors will be raised if timeout expires.
181
184
  # @option opts [ true | false ] :ssl Whether to use SSL.
182
185
  # @option opts [ String ] :ssl_ca_cert
183
186
  # Same as the corresponding Client/Socket::SSL option.
@@ -214,11 +217,12 @@ module Mongo
214
217
  # @since 2.0.0
215
218
  # @api private
216
219
  def socket(socket_timeout, opts = {})
220
+ csot = !!opts[:csot]
217
221
  opts = {
218
222
  connect_timeout: Server::CONNECT_TIMEOUT,
219
223
  }.update(options).update(Hash[opts.map { |k, v| [k.to_sym, v] }])
220
224
 
221
- map_exceptions do
225
+ map_exceptions(csot) do
222
226
  if seed.downcase =~ Unix::MATCH
223
227
  specific_address = Unix.new(seed.downcase)
224
228
  return specific_address.socket(socket_timeout, opts)
@@ -281,11 +285,26 @@ module Mongo
281
285
  end
282
286
  end
283
287
 
284
- def map_exceptions
288
+ # Maps some errors to different ones, mostly low-level errors to driver
289
+ # level errors
290
+ #
291
+ # @param [ Boolean ] csot Whether the client-side operation timeout
292
+ # should be considered when connecting the socket.
293
+ def map_exceptions(csot)
285
294
  begin
286
295
  yield
287
296
  rescue Errno::ETIMEDOUT => e
288
- raise Error::SocketTimeoutError, "#{e.class}: #{e} (for #{self})"
297
+ if csot
298
+ raise Error::TimeoutError, "#{e.class}: #{e} (for #{self})"
299
+ else
300
+ raise Error::SocketTimeoutError, "#{e.class}: #{e} (for #{self})"
301
+ end
302
+ rescue Error::SocketTimeoutError => e
303
+ if csot
304
+ raise Error::TimeoutError, "#{e.class}: #{e} (for #{self})"
305
+ else
306
+ raise e
307
+ end
289
308
  rescue IOError, SystemCallError => e
290
309
  raise Error::SocketError, "#{e.class}: #{e} (for #{self})"
291
310
  rescue OpenSSL::SSL::SSLError => e
@@ -69,20 +69,24 @@ module Mongo
69
69
  # Retrieves a valid set of credentials, if possible, or raises
70
70
  # Auth::InvalidConfiguration.
71
71
  #
72
+ # @param [ CsotTimeoutHolder | nil ] timeout_holder CSOT timeout, if any.
73
+ #
72
74
  # @return [ Auth::Aws::Credentials ] A valid set of credentials.
73
75
  #
74
76
  # @raise Auth::InvalidConfiguration if a source contains an invalid set
75
77
  # of credentials.
76
78
  # @raise Auth::Aws::CredentialsNotFound if credentials could not be
77
79
  # retrieved from any source.
78
- def credentials
80
+ # @raise Error::TimeoutError if credentials cannot be retrieved within
81
+ # the timeout defined on the operation context.
82
+ def credentials(timeout_holder = nil)
79
83
  credentials = credentials_from_user(user)
80
84
  return credentials unless credentials.nil?
81
85
 
82
86
  credentials = credentials_from_environment
83
87
  return credentials unless credentials.nil?
84
88
 
85
- credentials = @credentials_cache.fetch { obtain_credentials_from_endpoints }
89
+ credentials = @credentials_cache.fetch { obtain_credentials_from_endpoints(timeout_holder) }
86
90
  return credentials unless credentials.nil?
87
91
 
88
92
  raise Auth::Aws::CredentialsNotFound
@@ -127,17 +131,21 @@ module Mongo
127
131
 
128
132
  # Returns credentials from the AWS metadata endpoints.
129
133
  #
134
+ # @param [ CsotTimeoutHolder ] timeout_holder CSOT timeout.
135
+ #
130
136
  # @return [ Auth::Aws::Credentials | nil ] A set of credentials, or nil
131
137
  # if retrieval failed or the obtained credentials are invalid.
132
138
  #
133
139
  # @raise Auth::InvalidConfiguration if a source contains an invalid set
134
140
  # of credentials.
135
- def obtain_credentials_from_endpoints
136
- if (credentials = web_identity_credentials) && credentials_valid?(credentials, 'Web identity token')
141
+ # @ raise Error::TimeoutError if credentials cannot be retrieved within
142
+ # the timeout defined on the operation context.
143
+ def obtain_credentials_from_endpoints(timeout_holder = nil)
144
+ if (credentials = web_identity_credentials(timeout_holder)) && credentials_valid?(credentials, 'Web identity token')
137
145
  credentials
138
- elsif (credentials = ecs_metadata_credentials) && credentials_valid?(credentials, 'ECS task metadata')
146
+ elsif (credentials = ecs_metadata_credentials(timeout_holder)) && credentials_valid?(credentials, 'ECS task metadata')
139
147
  credentials
140
- elsif (credentials = ec2_metadata_credentials) && credentials_valid?(credentials, 'EC2 instance metadata')
148
+ elsif (credentials = ec2_metadata_credentials(timeout_holder)) && credentials_valid?(credentials, 'EC2 instance metadata')
141
149
  credentials
142
150
  end
143
151
  end
@@ -145,21 +153,26 @@ module Mongo
145
153
  # Returns credentials from the EC2 metadata endpoint. The credentials
146
154
  # could be empty, partial or invalid.
147
155
  #
156
+ # @param [ CsotTimeoutHolder ] timeout_holder CSOT timeout.
157
+ #
148
158
  # @return [ Auth::Aws::Credentials | nil ] A set of credentials, or nil
149
159
  # if retrieval failed.
150
- def ec2_metadata_credentials
160
+ # @ raise Error::TimeoutError if credentials cannot be retrieved within
161
+ # the timeout.
162
+ def ec2_metadata_credentials(timeout_holder = nil)
163
+ timeout_holder&.check_timeout!
151
164
  http = Net::HTTP.new('169.254.169.254')
152
165
  req = Net::HTTP::Put.new('/latest/api/token',
153
166
  # The TTL is required in order to obtain the metadata token.
154
167
  {'x-aws-ec2-metadata-token-ttl-seconds' => '30'})
155
- resp = ::Timeout.timeout(METADATA_TIMEOUT) do
168
+ resp = with_timeout(timeout_holder) do
156
169
  http.request(req)
157
170
  end
158
171
  if resp.code != '200'
159
172
  return nil
160
173
  end
161
174
  metadata_token = resp.body
162
- resp = ::Timeout.timeout(METADATA_TIMEOUT) do
175
+ resp = with_timeout(timeout_holder) do
163
176
  http_get(http, '/latest/meta-data/iam/security-credentials', metadata_token)
164
177
  end
165
178
  if resp.code != '200'
@@ -167,7 +180,7 @@ module Mongo
167
180
  end
168
181
  role_name = resp.body
169
182
  escaped_role_name = CGI.escape(role_name).gsub('+', '%20')
170
- resp = ::Timeout.timeout(METADATA_TIMEOUT) do
183
+ resp = with_timeout(timeout_holder) do
171
184
  http_get(http, "/latest/meta-data/iam/security-credentials/#{escaped_role_name}", metadata_token)
172
185
  end
173
186
  if resp.code != '200'
@@ -189,7 +202,17 @@ module Mongo
189
202
  return nil
190
203
  end
191
204
 
192
- def ecs_metadata_credentials
205
+ # Returns credentials from the ECS metadata endpoint. The credentials
206
+ # could be empty, partial or invalid.
207
+ #
208
+ # @param [ CsotTimeoutHolder | nil ] timeout_holder CSOT timeout.
209
+ #
210
+ # @return [ Auth::Aws::Credentials | nil ] A set of credentials, or nil
211
+ # if retrieval failed.
212
+ # @ raise Error::TimeoutError if credentials cannot be retrieved within
213
+ # the timeout defined on the operation context.
214
+ def ecs_metadata_credentials(timeout_holder = nil)
215
+ timeout_holder&.check_timeout!
193
216
  relative_uri = ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']
194
217
  if relative_uri.nil? || relative_uri.empty?
195
218
  return nil
@@ -203,7 +226,7 @@ module Mongo
203
226
  # a leading slash must be added by the driver, but this is not
204
227
  # in fact needed.
205
228
  req = Net::HTTP::Get.new(relative_uri)
206
- resp = ::Timeout.timeout(METADATA_TIMEOUT) do
229
+ resp = with_timeout(timeout_holder) do
207
230
  http.request(req)
208
231
  end
209
232
  if resp.code != '200'
@@ -225,13 +248,15 @@ module Mongo
225
248
  # inside EKS. See https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
226
249
  # for further details.
227
250
  #
251
+ # @param [ CsotTimeoutHolder | nil ] timeout_holder CSOT timeout.
252
+ #
228
253
  # @return [ Auth::Aws::Credentials | nil ] A set of credentials, or nil
229
254
  # if retrieval failed.
230
- def web_identity_credentials
255
+ def web_identity_credentials(timeout_holder = nil)
231
256
  web_identity_token, role_arn, role_session_name = prepare_web_identity_inputs
232
257
  return nil if web_identity_token.nil?
233
258
  response = request_web_identity_credentials(
234
- web_identity_token, role_arn, role_session_name
259
+ web_identity_token, role_arn, role_session_name, timeout_holder
235
260
  )
236
261
  return if response.nil?
237
262
  credentials_from_web_identity_response(response)
@@ -266,10 +291,15 @@ module Mongo
266
291
  # that the caller is assuming.
267
292
  # @param [ String ] role_session_name An identifier for the assumed
268
293
  # role session.
294
+ # @param [ CsotTimeoutHolder | nil ] timeout_holder CSOT timeout.
269
295
  #
270
296
  # @return [ Net::HTTPResponse | nil ] AWS API response if successful,
271
297
  # otherwise nil.
272
- def request_web_identity_credentials(token, role_arn, role_session_name)
298
+ #
299
+ # @ raise Error::TimeoutError if credentials cannot be retrieved within
300
+ # the timeout defined on the operation context.
301
+ def request_web_identity_credentials(token, role_arn, role_session_name, timeout_holder)
302
+ timeout_holder&.check_timeout!
273
303
  uri = URI('https://sts.amazonaws.com/')
274
304
  params = {
275
305
  'Action' => 'AssumeRoleWithWebIdentity',
@@ -281,8 +311,10 @@ module Mongo
281
311
  uri.query = ::URI.encode_www_form(params)
282
312
  req = Net::HTTP::Post.new(uri)
283
313
  req['Accept'] = 'application/json'
284
- resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |https|
285
- https.request(req)
314
+ resp = with_timeout(timeout_holder) do
315
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |https|
316
+ https.request(req)
317
+ end
286
318
  end
287
319
  if resp.code != '200'
288
320
  return nil
@@ -351,6 +383,27 @@ module Mongo
351
383
 
352
384
  true
353
385
  end
386
+
387
+ # Execute the given block considering the timeout defined on the context,
388
+ # or the default timeout value.
389
+ #
390
+ # We use +Timeout.timeout+ here because there is no other acceptable easy
391
+ # way to time limit http requests.
392
+ #
393
+ # @param [ CsotTimeoutHolder | nil ] timeout_holder CSOT timeout.
394
+ #
395
+ # @ raise Error::TimeoutError if deadline exceeded.
396
+ def with_timeout(timeout_holder)
397
+ timeout = timeout_holder&.remaining_timeout_sec! || METADATA_TIMEOUT
398
+ exception_class = if timeout_holder&.csot?
399
+ Error::TimeoutError
400
+ else
401
+ nil
402
+ end
403
+ ::Timeout.timeout(timeout, exception_class) do
404
+ yield
405
+ end
406
+ end
354
407
  end
355
408
  end
356
409
  end
@@ -117,7 +117,7 @@ module Mongo
117
117
  else
118
118
  nil
119
119
  end
120
- result = Operation::Result.new(reply, connection.description, connection_global_id)
120
+ result = Operation::Result.new(reply, connection.description, connection_global_id, context: context)
121
121
  connection.update_cluster_time(result)
122
122
  reply_document
123
123
  end
@@ -60,10 +60,15 @@ module Mongo
60
60
  result_combiner = ResultCombiner.new
61
61
  operations = op_combiner.combine
62
62
  validate_requests!
63
+ deadline = calculate_deadline
63
64
 
64
- client.send(:with_session, @options) do |session|
65
- context = Operation::Context.new(client: client, session: session)
65
+ client.with_session(@options) do |session|
66
66
  operations.each do |operation|
67
+ context = Operation::Context.new(
68
+ client: client,
69
+ session: session,
70
+ operation_timeouts: { operation_timeout_ms: op_timeout_ms(deadline) }
71
+ )
67
72
  if single_statement?(operation)
68
73
  write_concern = write_concern(session)
69
74
  write_with_retry(write_concern, context: context) do |connection, txn_num, context|
@@ -124,6 +129,9 @@ module Mongo
124
129
  @collection = collection
125
130
  @requests = requests
126
131
  @options = options || {}
132
+ if @options[:timeout_ms] && @options[:timeout_ms] < 0
133
+ raise ArgumentError, "timeout_ms options must be non-negative integer"
134
+ end
127
135
  end
128
136
 
129
137
  # Is the bulk write ordered?
@@ -162,6 +170,31 @@ module Mongo
162
170
  :update_one,
163
171
  :insert_one ].freeze
164
172
 
173
+ # @return [ Float | nil ] Deadline for the batch of operations, if set.
174
+ def calculate_deadline
175
+ timeout_ms = @options[:timeout_ms] || collection.timeout_ms
176
+ return nil if timeout_ms.nil?
177
+
178
+ if timeout_ms == 0
179
+ 0
180
+ else
181
+ Utils.monotonic_time + (timeout_ms / 1_000.0)
182
+ end
183
+ end
184
+
185
+ # @param [ Float | nil ] deadline Deadline for the batch of operations.
186
+ #
187
+ # @return [ Integer | nil ] Timeout in milliseconds for the next operation.
188
+ def op_timeout_ms(deadline)
189
+ return nil if deadline.nil?
190
+
191
+ if deadline == 0
192
+ 0
193
+ else
194
+ ((deadline - Utils.monotonic_time) * 1_000).to_i
195
+ end
196
+ end
197
+
165
198
  def single_statement?(operation)
166
199
  SINGLE_STATEMENT_OPS.include?(operation.keys.first)
167
200
  end
data/lib/mongo/client.rb CHANGED
@@ -111,6 +111,7 @@ module Mongo
111
111
  :ssl_verify_certificate,
112
112
  :ssl_verify_hostname,
113
113
  :ssl_verify_ocsp_endpoint,
114
+ :timeout_ms,
114
115
  :truncate_logs,
115
116
  :user,
116
117
  :wait_queue_timeout,
@@ -349,7 +350,8 @@ module Mongo
349
350
  # @option options [ Integer ] :server_selection_timeout The timeout in seconds
350
351
  # for selecting a server for an operation.
351
352
  # @option options [ Float ] :socket_timeout The timeout, in seconds, to
352
- # execute operations on a socket.
353
+ # execute operations on a socket. This option is deprecated, use
354
+ # :timeout_ms instead.
353
355
  # @option options [ Integer ] :srv_max_hosts The maximum number of mongoses
354
356
  # that the driver will communicate with for sharded topologies. If this
355
357
  # option is 0, then there will be no maximum number of mongoses. If the
@@ -413,11 +415,15 @@ module Mongo
413
415
  # @option options [ true, false ] :ssl_verify_hostname Whether to perform peer hostname
414
416
  # validation. This setting overrides :ssl_verify with respect to whether hostname validation
415
417
  # is performed.
418
+ # @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
419
+ # Must be a non-negative integer. An explicit value of 0 means infinite.
420
+ # The default value is unset which means the feature is not enabled.
416
421
  # @option options [ true, false ] :truncate_logs Whether to truncate the
417
422
  # logs at the default 250 characters.
418
423
  # @option options [ String ] :user The user name.
419
424
  # @option options [ Float ] :wait_queue_timeout The time to wait, in
420
425
  # seconds, in the connection pool for a connection to be checked in.
426
+ # This option is deprecated, use :timeout_ms instead.
421
427
  # @option options [ Array<Hash> ] :wrapping_libraries Information about
422
428
  # libraries such as ODMs that are wrapping the driver, to be added to
423
429
  # metadata sent to the server. Specify the lower level libraries first.
@@ -425,7 +431,7 @@ module Mongo
425
431
  # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
426
432
  # option.
427
433
  # @option options [ Hash ] :write_concern The write concern options.
428
- # Can be :w => Integer|String, :wtimeout => Integer (in milliseconds),
434
+ # Can be :w => Integer|String, :wtimeout => Integer (in milliseconds, deprecated),
429
435
  # :j => Boolean, :fsync => Boolean.
430
436
  # @option options [ Integer ] :zlib_compression_level The Zlib compression level to use, if using compression.
431
437
  # See Ruby's Zlib module for valid levels.
@@ -934,8 +940,11 @@ module Mongo
934
940
  # See https://mongodb.com/docs/manual/reference/command/listDatabases/
935
941
  # for more information and usage.
936
942
  # @option opts [ Session ] :session The session to use.
937
- # @option options [ Object ] :comment A user-provided
943
+ # @option opts [ Object ] :comment A user-provided
938
944
  # comment to attach to this command.
945
+ # @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
946
+ # Must be a non-negative integer. An explicit value of 0 means infinite.
947
+ # The default value is unset which means the feature is not enabled.
939
948
  #
940
949
  # @return [ Array<String> ] The names of the databases.
941
950
  #
@@ -955,7 +964,12 @@ module Mongo
955
964
  #
956
965
  # @option opts [ true, false ] :authorized_databases A flag that determines
957
966
  # which databases are returned based on user privileges when access control
958
- # is enabled
967
+ # is enabled.
968
+ # @option opts [ Object ] :comment A user-provided
969
+ # comment to attach to this command.
970
+ # @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
971
+ # Must be a non-negative integer. An explicit value of 0 means infinite.
972
+ # The default value is unset which means the feature is not enabled.
959
973
  #
960
974
  # See https://mongodb.com/docs/manual/reference/command/listDatabases/
961
975
  # for more information and usage.
@@ -1095,7 +1109,7 @@ module Mongo
1095
1109
  return use(Database::ADMIN).watch(pipeline, options) unless database.name == Database::ADMIN
1096
1110
 
1097
1111
  view_options = options.dup
1098
- view_options[:await_data] = true if options[:max_await_time_ms]
1112
+ view_options[:cursor_type] = :tailable_await if options[:max_await_time_ms]
1099
1113
 
1100
1114
  Mongo::Collection::View::ChangeStream.new(
1101
1115
  Mongo::Collection::View.new(self["#{Database::COMMAND}.aggregate"], {}, view_options),
@@ -1185,6 +1199,22 @@ module Mongo
1185
1199
  @encrypted_fields_map ||= @options.fetch(:auto_encryption_options, {})[:encrypted_fields_map]
1186
1200
  end
1187
1201
 
1202
+ # @return [ Integer | nil ] Value of timeout_ms option if set.
1203
+ # @api private
1204
+ def timeout_ms
1205
+ @options[:timeout_ms]
1206
+ end
1207
+
1208
+ # @return [ Float | nil ] Value of timeout_ms option converted to seconds.
1209
+ # @api private
1210
+ def timeout_sec
1211
+ if timeout_ms.nil?
1212
+ nil
1213
+ else
1214
+ timeout_ms / 1_000.0
1215
+ end
1216
+ end
1217
+
1188
1218
  private
1189
1219
 
1190
1220
  # Create a new encrypter object using the client's auto encryption options
@@ -1230,6 +1260,8 @@ module Mongo
1230
1260
  # @option options [ true | false ] :implicit When no session is passed in,
1231
1261
  # whether to create an implicit session.
1232
1262
  # @option options [ Session ] :session The session to validate and return.
1263
+ # @option options [ Operation::Context | nil ] :context Context of the
1264
+ # operation the session is used for.
1233
1265
  #
1234
1266
  # @return [ Session ] A session object.
1235
1267
  #
@@ -1242,7 +1274,7 @@ module Mongo
1242
1274
  return options[:session].validate!(self)
1243
1275
  end
1244
1276
 
1245
- cluster.validate_session_support!
1277
+ cluster.validate_session_support!(timeout: timeout_sec)
1246
1278
 
1247
1279
  options = {implicit: true}.update(options)
1248
1280
 
@@ -40,6 +40,9 @@ module Mongo
40
40
  # should be hashes of TLS connection options. The options are equivalent
41
41
  # to TLS connection options of Mongo::Client.
42
42
  # @see Mongo::Client#initialize for list of TLS options.
43
+ # @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
44
+ # Must be a non-negative integer. An explicit value of 0 means infinite.
45
+ # The default value is unset which means the feature is disabled.
43
46
  #
44
47
  # @raise [ ArgumentError ] If required options are missing or incorrectly
45
48
  # formatted.
@@ -131,7 +134,7 @@ module Mongo
131
134
  # {'$and' => [{'$gt' => ['$field', 10]}, {'$lt' => ['$field', 20]}}
132
135
  # )
133
136
  # {$and: [{$gt: [<fieldpath>, <value1>]}, {$lt: [<fieldpath>, <value2>]}]
134
- # Only supported when queryType is "rangePreview" and algorithm is "RangePreview".
137
+ # Only supported when queryType is "range" and algorithm is "Range".
135
138
  # @note: The Range algorithm is experimental only. It is not intended
136
139
  # for public use. It is subject to breaking changes.
137
140
  #
@@ -143,11 +146,11 @@ module Mongo
143
146
  # @option options [ String ] :key_alt_name The alternate name for the
144
147
  # encryption key.
145
148
  # @option options [ String ] :algorithm The algorithm used to encrypt the
146
- # expression. The only allowed value is "RangePreview"
149
+ # expression. The only allowed value is "Range"
147
150
  # @option options [ Integer | nil ] :contention_factor Contention factor
148
151
  # to be applied If not provided, it defaults to a value of 0.
149
152
  # @option options [ String | nil ] query_type Query type to be applied.
150
- # The only allowed value is "rangePreview".
153
+ # The only allowed value is "range".
151
154
  #
152
155
  # @note The :key_id and :key_alt_name options are mutually exclusive. Only
153
156
  # one is required to perform explicit encryption.
@@ -194,7 +194,12 @@ module Mongo
194
194
  server_api: server.options[:server_api],
195
195
  connection_global_id: kill_spec.connection_global_id,
196
196
  }
197
- op.execute(server, context: Operation::Context.new(options: options))
197
+ if connection = kill_spec.connection
198
+ op.execute_with_connection(connection, context: Operation::Context.new(options: options))
199
+ connection.connection_pool.check_in(connection)
200
+ else
201
+ op.execute(server, context: Operation::Context.new(options: options))
202
+ end
198
203
 
199
204
  if session = kill_spec.session
200
205
  if session.implicit?
@@ -116,8 +116,12 @@ class Mongo::Cluster
116
116
  log_warn(
117
117
  "Server #{updated_desc.address.to_s} has an incorrect replica set name '#{updated_desc.replica_set_name}'; expected '#{topology.replica_set_name}'"
118
118
  )
119
- @updated_desc = ::Mongo::Server::Description.new(updated_desc.address,
120
- {}, average_round_trip_time: updated_desc.average_round_trip_time)
119
+ @updated_desc = ::Mongo::Server::Description.new(
120
+ updated_desc.address,
121
+ {},
122
+ average_round_trip_time: updated_desc.average_round_trip_time,
123
+ minimum_round_trip_time: updated_desc.minimum_round_trip_time
124
+ )
121
125
  update_server_descriptions
122
126
  end
123
127
  end
@@ -233,8 +237,12 @@ class Mongo::Cluster
233
237
  end
234
238
 
235
239
  if stale_primary?
236
- @updated_desc = ::Mongo::Server::Description.new(updated_desc.address,
237
- {}, average_round_trip_time: updated_desc.average_round_trip_time)
240
+ @updated_desc = ::Mongo::Server::Description.new(
241
+ updated_desc.address,
242
+ {},
243
+ average_round_trip_time: updated_desc.average_round_trip_time,
244
+ minimum_round_trip_time: updated_desc.minimum_round_trip_time
245
+ )
238
246
  update_server_descriptions
239
247
  check_if_has_primary
240
248
  return
@@ -270,9 +278,14 @@ class Mongo::Cluster
270
278
  servers_list.each do |server|
271
279
  if server.address != updated_desc.address
272
280
  if server.primary?
273
- server.update_description(::Mongo::Server::Description.new(
274
- server.address, {},
275
- average_round_trip_time: server.description.average_round_trip_time))
281
+ server.update_description(
282
+ ::Mongo::Server::Description.new(
283
+ server.address,
284
+ {},
285
+ average_round_trip_time: server.description.average_round_trip_time,
286
+ minimum_round_trip_time: updated_desc.minimum_round_trip_time
287
+ )
288
+ )
276
289
  end
277
290
  end
278
291
  end
data/lib/mongo/cluster.rb CHANGED
@@ -779,12 +779,19 @@ module Mongo
779
779
  # Deprecated and ignored.
780
780
  # @param [ Session | nil ] session Optional session to take into account
781
781
  # for mongos pinning.
782
+ # @param [ Float | nil ] :timeout Timeout in seconds for the operation,
783
+ # if any.
782
784
  #
783
785
  # @return [ Mongo::Server ] A primary server.
784
786
  #
785
787
  # @since 2.0.0
786
- def next_primary(ping = nil, session = nil)
787
- ServerSelector.primary.select_server(self, nil, session)
788
+ def next_primary(ping = nil, session = nil, timeout: nil)
789
+ ServerSelector.primary.select_server(
790
+ self,
791
+ nil,
792
+ session,
793
+ timeout: timeout
794
+ )
788
795
  end
789
796
 
790
797
  # Get the connection pool for the server.
@@ -974,8 +981,11 @@ module Mongo
974
981
  # any servers and doesn't find any servers for the duration of
975
982
  # server selection timeout.
976
983
  #
984
+ # @param [ Float | nil ] :timeout Timeout for the validation. Since the
985
+ # validation process involves server selection,
986
+ #
977
987
  # @api private
978
- def validate_session_support!
988
+ def validate_session_support!(timeout: nil)
979
989
  if topology.is_a?(Topology::LoadBalanced)
980
990
  return
981
991
  end
@@ -993,7 +1003,7 @@ module Mongo
993
1003
  # No data bearing servers known - perform server selection to try to
994
1004
  # get a response from at least one of them, to return an accurate
995
1005
  # assessment of whether sessions are currently supported.
996
- ServerSelector.get(mode: :primary_preferred).select_server(self)
1006
+ ServerSelector.get(mode: :primary_preferred).select_server(self, timeout: timeout)
997
1007
  @state_change_lock.synchronize do
998
1008
  @sdam_flow_lock.synchronize do
999
1009
  unless topology.logical_session_timeout
@@ -30,7 +30,7 @@ module Mongo
30
30
  # @return [ Result ] The result of the execution.
31
31
  def do_drop(operation, session, context)
32
32
  operation.execute(next_primary(nil, session), context: context)
33
- rescue Error::OperationFailure => ex
33
+ rescue Error::OperationFailure::Family => ex
34
34
  # NamespaceNotFound
35
35
  if ex.code == 26 || ex.code.nil? && ex.message =~ /ns not found/
36
36
  false