mongo 2.19.1 → 2.21.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 (356) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -1
  3. data/Rakefile +83 -174
  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/topology/base.rb +16 -0
  13. data/lib/mongo/cluster.rb +41 -5
  14. data/lib/mongo/collection/helpers.rb +1 -1
  15. data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
  16. data/lib/mongo/collection/view/aggregation.rb +33 -99
  17. data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
  18. data/lib/mongo/collection/view/change_stream.rb +80 -27
  19. data/lib/mongo/collection/view/iterable.rb +92 -60
  20. data/lib/mongo/collection/view/map_reduce.rb +25 -8
  21. data/lib/mongo/collection/view/readable.rb +79 -30
  22. data/lib/mongo/collection/view/writable.rb +109 -48
  23. data/lib/mongo/collection/view.rb +44 -3
  24. data/lib/mongo/collection.rb +185 -26
  25. data/lib/mongo/config.rb +2 -2
  26. data/lib/mongo/crypt/auto_encrypter.rb +4 -6
  27. data/lib/mongo/crypt/binding.rb +4 -4
  28. data/lib/mongo/crypt/context.rb +20 -14
  29. data/lib/mongo/crypt/encryption_io.rb +56 -26
  30. data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
  31. data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
  32. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
  33. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
  34. data/lib/mongo/csot_timeout_holder.rb +119 -0
  35. data/lib/mongo/cursor/kill_spec.rb +5 -2
  36. data/lib/mongo/cursor/nontailable.rb +27 -0
  37. data/lib/mongo/cursor.rb +86 -24
  38. data/lib/mongo/cursor_host.rb +82 -0
  39. data/lib/mongo/database/view.rb +81 -14
  40. data/lib/mongo/database.rb +88 -18
  41. data/lib/mongo/error/operation_failure.rb +209 -204
  42. data/lib/mongo/error/server_timeout_error.rb +12 -0
  43. data/lib/mongo/error/socket_timeout_error.rb +3 -1
  44. data/lib/mongo/error/timeout_error.rb +23 -0
  45. data/lib/mongo/error/transactions_not_supported.rb +34 -0
  46. data/lib/mongo/error.rb +3 -0
  47. data/lib/mongo/grid/fs_bucket.rb +48 -9
  48. data/lib/mongo/grid/stream/read.rb +15 -1
  49. data/lib/mongo/grid/stream/write.rb +21 -4
  50. data/lib/mongo/index/view.rb +77 -16
  51. data/lib/mongo/monitoring/event/secure.rb +1 -1
  52. data/lib/mongo/operation/context.rb +40 -2
  53. data/lib/mongo/operation/create_search_indexes/op_msg.rb +31 -0
  54. data/lib/mongo/operation/create_search_indexes.rb +15 -0
  55. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  56. data/lib/mongo/operation/drop_search_index/op_msg.rb +33 -0
  57. data/lib/mongo/operation/drop_search_index.rb +15 -0
  58. data/lib/mongo/operation/find/op_msg.rb +45 -0
  59. data/lib/mongo/operation/get_more/op_msg.rb +33 -0
  60. data/lib/mongo/operation/insert/op_msg.rb +3 -2
  61. data/lib/mongo/operation/insert/result.rb +4 -2
  62. data/lib/mongo/operation/list_collections/result.rb +1 -1
  63. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  64. data/lib/mongo/operation/op_msg_base.rb +3 -1
  65. data/lib/mongo/operation/result.rb +26 -5
  66. data/lib/mongo/operation/shared/executable.rb +55 -28
  67. data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
  68. data/lib/mongo/operation/shared/response_handling.rb +25 -27
  69. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  70. data/lib/mongo/operation/shared/specifiable.rb +7 -0
  71. data/lib/mongo/operation/shared/timed.rb +52 -0
  72. data/lib/mongo/operation/shared/write.rb +4 -1
  73. data/lib/mongo/operation/update/op_msg.rb +2 -1
  74. data/lib/mongo/operation/update_search_index/op_msg.rb +34 -0
  75. data/lib/mongo/operation/update_search_index.rb +15 -0
  76. data/lib/mongo/operation.rb +4 -0
  77. data/lib/mongo/protocol/message.rb +1 -4
  78. data/lib/mongo/protocol/msg.rb +2 -2
  79. data/lib/mongo/retryable/base_worker.rb +28 -3
  80. data/lib/mongo/retryable/read_worker.rb +78 -36
  81. data/lib/mongo/retryable/write_worker.rb +59 -25
  82. data/lib/mongo/retryable.rb +8 -2
  83. data/lib/mongo/search_index/view.rb +232 -0
  84. data/lib/mongo/server/app_metadata/environment.rb +64 -9
  85. data/lib/mongo/server/app_metadata.rb +5 -4
  86. data/lib/mongo/server/connection.rb +11 -5
  87. data/lib/mongo/server/connection_base.rb +22 -2
  88. data/lib/mongo/server/connection_pool.rb +32 -14
  89. data/lib/mongo/server/description/features.rb +2 -1
  90. data/lib/mongo/server/description.rb +18 -5
  91. data/lib/mongo/server/monitor.rb +7 -4
  92. data/lib/mongo/server/pending_connection.rb +25 -8
  93. data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
  94. data/lib/mongo/server.rb +11 -6
  95. data/lib/mongo/server_selector/base.rb +54 -12
  96. data/lib/mongo/session/server_session/dirtyable.rb +52 -0
  97. data/lib/mongo/session/server_session.rb +3 -0
  98. data/lib/mongo/session/session_pool.rb +12 -18
  99. data/lib/mongo/session.rb +110 -9
  100. data/lib/mongo/socket/ssl.rb +131 -18
  101. data/lib/mongo/socket/tcp.rb +40 -6
  102. data/lib/mongo/socket.rb +154 -25
  103. data/lib/mongo/uri/options_mapper.rb +1 -0
  104. data/lib/mongo/uri.rb +0 -4
  105. data/lib/mongo/version.rb +1 -5
  106. data/lib/mongo.rb +2 -0
  107. data/mongo.gemspec +9 -18
  108. data/spec/atlas/atlas_connectivity_spec.rb +9 -9
  109. data/spec/atlas/operations_spec.rb +5 -5
  110. data/spec/faas/ruby-sam-app/Gemfile +9 -0
  111. data/spec/faas/ruby-sam-app/mongodb/Gemfile +4 -0
  112. data/spec/faas/ruby-sam-app/mongodb/app.rb +149 -0
  113. data/spec/faas/ruby-sam-app/template.yaml +48 -0
  114. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
  115. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
  116. data/spec/integration/client_side_encryption/corpus_spec.rb +10 -2
  117. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
  118. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +67 -20
  119. data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
  120. data/spec/integration/connection_pool_populator_spec.rb +2 -0
  121. data/spec/integration/cursor_pinning_spec.rb +15 -60
  122. data/spec/integration/cursor_reaping_spec.rb +1 -1
  123. data/spec/integration/docs_examples_spec.rb +1 -1
  124. data/spec/integration/find_options_spec.rb +227 -0
  125. data/spec/integration/operation_failure_code_spec.rb +1 -1
  126. data/spec/integration/operation_failure_message_spec.rb +3 -3
  127. data/spec/integration/retryable_errors_spec.rb +2 -2
  128. data/spec/integration/retryable_reads_errors_spec.rb +196 -31
  129. data/spec/integration/retryable_writes_errors_spec.rb +156 -0
  130. data/spec/integration/sdam_error_handling_spec.rb +4 -1
  131. data/spec/integration/search_indexes_prose_spec.rb +172 -0
  132. data/spec/integration/server_spec.rb +4 -3
  133. data/spec/integration/transactions_api_examples_spec.rb +2 -0
  134. data/spec/kerberos/kerberos_spec.rb +4 -0
  135. data/spec/lite_spec_helper.rb +34 -20
  136. data/spec/mongo/auth/user/view_spec.rb +1 -1
  137. data/spec/mongo/caching_cursor_spec.rb +1 -1
  138. data/spec/mongo/client_encryption_spec.rb +1 -0
  139. data/spec/mongo/client_spec.rb +158 -4
  140. data/spec/mongo/cluster_spec.rb +36 -0
  141. data/spec/mongo/collection/view/aggregation_spec.rb +20 -40
  142. data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
  143. data/spec/mongo/collection/view/explainable_spec.rb +2 -0
  144. data/spec/mongo/collection_crud_spec.rb +2 -1
  145. data/spec/mongo/collection_spec.rb +5 -6
  146. data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
  147. data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
  148. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
  149. data/spec/mongo/crypt/handle_spec.rb +1 -1
  150. data/spec/mongo/cursor_spec.rb +26 -9
  151. data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
  152. data/spec/mongo/operation/context_spec.rb +79 -0
  153. data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
  154. data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
  155. data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
  156. data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
  157. data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
  158. data/spec/mongo/operation/insert_spec.rb +1 -1
  159. data/spec/mongo/operation/shared/csot/examples.rb +113 -0
  160. data/spec/mongo/query_cache_spec.rb +243 -225
  161. data/spec/mongo/retryable/write_worker_spec.rb +39 -0
  162. data/spec/mongo/retryable_spec.rb +1 -0
  163. data/spec/mongo/server/app_metadata/environment_spec.rb +135 -0
  164. data/spec/mongo/server/app_metadata_spec.rb +12 -2
  165. data/spec/mongo/server/connection_spec.rb +26 -0
  166. data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
  167. data/spec/mongo/session/session_pool_spec.rb +1 -16
  168. data/spec/mongo/session_transaction_spec.rb +15 -0
  169. data/spec/mongo/socket/ssl_spec.rb +0 -10
  170. data/spec/mongo/uri_spec.rb +0 -9
  171. data/spec/runners/change_streams/test.rb +2 -2
  172. data/spec/runners/crud/operation.rb +1 -1
  173. data/spec/runners/crud/test.rb +0 -8
  174. data/spec/runners/crud/verifier.rb +3 -1
  175. data/spec/runners/crud.rb +1 -1
  176. data/spec/runners/transactions/operation.rb +4 -6
  177. data/spec/runners/transactions/test.rb +12 -3
  178. data/spec/runners/unified/ambiguous_operations.rb +13 -0
  179. data/spec/runners/unified/assertions.rb +20 -3
  180. data/spec/runners/unified/change_stream_operations.rb +14 -24
  181. data/spec/runners/unified/crud_operations.rb +82 -47
  182. data/spec/runners/unified/ddl_operations.rb +38 -7
  183. data/spec/runners/unified/grid_fs_operations.rb +37 -2
  184. data/spec/runners/unified/search_index_operations.rb +63 -0
  185. data/spec/runners/unified/support_operations.rb +46 -9
  186. data/spec/runners/unified/test.rb +33 -12
  187. data/spec/runners/unified.rb +1 -1
  188. data/spec/solo/clean_exit_spec.rb +2 -0
  189. data/spec/spec_helper.rb +1 -1
  190. data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
  191. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
  192. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
  193. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
  194. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  195. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
  196. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
  197. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
  198. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
  199. data/spec/spec_tests/data/client_side_encryption/explain.yml +2 -2
  200. data/spec/spec_tests/data/client_side_encryption/fle2v2-BypassQueryAnalysis.yml +1 -0
  201. data/spec/spec_tests/data/client_side_encryption/fle2v2-Compact.yml +1 -0
  202. data/spec/spec_tests/data/client_side_encryption/fle2v2-CreateCollection.yml +1 -0
  203. data/spec/spec_tests/data/client_side_encryption/fle2v2-DecryptExistingData.yml +1 -0
  204. data/spec/spec_tests/data/client_side_encryption/fle2v2-Delete.yml +1 -0
  205. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-EncryptedFieldsMap.yml +1 -0
  206. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-jsonSchema.yml +1 -0
  207. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFieldsMap-defaults.yml +1 -0
  208. data/spec/spec_tests/data/client_side_encryption/fle2v2-FindOneAndUpdate.yml +1 -0
  209. data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Indexed.yml +1 -0
  210. data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Unindexed.yml +1 -0
  211. data/spec/spec_tests/data/client_side_encryption/fle2v2-MissingKey.yml +1 -0
  212. data/spec/spec_tests/data/client_side_encryption/fle2v2-NoEncryption.yml +1 -0
  213. data/spec/spec_tests/data/client_side_encryption/fle2v2-Update.yml +1 -0
  214. data/spec/spec_tests/data/client_side_encryption/fle2v2-validatorAndPartialFieldExpression.yml +2 -1
  215. data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
  216. data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
  217. data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
  218. data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
  219. data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
  220. data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
  221. data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
  222. data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
  223. data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
  224. data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
  225. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
  226. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
  227. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
  228. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
  229. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
  230. data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
  231. data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
  232. data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
  233. data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
  234. data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
  235. data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
  236. data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
  237. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
  238. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
  239. data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
  240. data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
  241. data/spec/spec_tests/data/connection_string/invalid-uris.yml +0 -10
  242. data/spec/spec_tests/data/connection_string/valid-options.yml +13 -0
  243. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +6 -0
  244. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +6 -0
  245. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +377 -0
  246. data/spec/spec_tests/data/index_management/createSearchIndex.yml +64 -0
  247. data/spec/spec_tests/data/index_management/createSearchIndexes.yml +86 -0
  248. data/spec/spec_tests/data/index_management/dropSearchIndex.yml +43 -0
  249. data/spec/spec_tests/data/index_management/listSearchIndexes.yml +91 -0
  250. data/spec/spec_tests/data/index_management/updateSearchIndex.yml +46 -0
  251. data/spec/spec_tests/data/retryable_writes/unified/bulkWrite-serverErrors.yml +3 -6
  252. data/spec/spec_tests/data/retryable_writes/unified/insertOne-serverErrors.yml +3 -6
  253. data/spec/spec_tests/data/run_command_unified/runCommand.yml +319 -0
  254. data/spec/spec_tests/data/sessions_unified/driver-sessions-dirty-session-errors.yml +351 -0
  255. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +1 -1
  256. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +7 -7
  257. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +3 -4
  258. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +1 -1
  259. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +1 -1
  260. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +3 -3
  261. data/spec/spec_tests/index_management_unified_spec.rb +13 -0
  262. data/spec/spec_tests/run_command_unified_spec.rb +13 -0
  263. data/spec/spec_tests/sdam_unified_spec.rb +2 -0
  264. data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
  265. data/spec/spec_tests/transactions_unified_spec.rb +2 -1
  266. data/spec/support/certificates/atlas-ocsp-ca.crt +89 -79
  267. data/spec/support/certificates/atlas-ocsp.crt +117 -122
  268. data/spec/support/certificates/retrieve-atlas-cert +1 -1
  269. data/spec/support/cluster_tools.rb +3 -3
  270. data/spec/support/common_shortcuts.rb +2 -2
  271. data/spec/support/constraints.rb +6 -0
  272. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
  273. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
  274. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
  275. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
  276. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
  277. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
  278. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
  279. data/spec/support/ocsp +1 -1
  280. data/spec/support/recording_logger.rb +27 -0
  281. data/spec/support/shared/session.rb +2 -2
  282. data/spec/support/spec_config.rb +5 -0
  283. data/spec/support/spec_setup.rb +2 -2
  284. data/spec/support/utils.rb +3 -1
  285. metadata +1329 -1368
  286. checksums.yaml.gz.sig +0 -0
  287. data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
  288. data/spec/shared/LICENSE +0 -20
  289. data/spec/shared/bin/get-mongodb-download-url +0 -17
  290. data/spec/shared/bin/s3-copy +0 -45
  291. data/spec/shared/bin/s3-upload +0 -69
  292. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  293. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  294. data/spec/shared/lib/mrss/constraints.rb +0 -378
  295. data/spec/shared/lib/mrss/docker_runner.rb +0 -295
  296. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  297. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  298. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  299. data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
  300. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  301. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  302. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  303. data/spec/shared/lib/mrss/utils.rb +0 -37
  304. data/spec/shared/share/Dockerfile.erb +0 -330
  305. data/spec/shared/share/haproxy-1.conf +0 -16
  306. data/spec/shared/share/haproxy-2.conf +0 -17
  307. data/spec/shared/shlib/config.sh +0 -27
  308. data/spec/shared/shlib/distro.sh +0 -74
  309. data/spec/shared/shlib/server.sh +0 -416
  310. data/spec/shared/shlib/set_env.sh +0 -169
  311. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -241
  312. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -422
  313. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -182
  314. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -239
  315. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -235
  316. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -252
  317. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1687
  318. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -293
  319. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -905
  320. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1684
  321. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1680
  322. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1697
  323. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -329
  324. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -424
  325. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -226
  326. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -327
  327. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -319
  328. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -336
  329. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -913
  330. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -292
  331. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -518
  332. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -911
  333. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -907
  334. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -924
  335. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -325
  336. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -424
  337. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -224
  338. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -323
  339. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -319
  340. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -338
  341. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -241
  342. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -423
  343. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -182
  344. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -239
  345. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -235
  346. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -254
  347. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -241
  348. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -422
  349. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -182
  350. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -239
  351. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -235
  352. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -254
  353. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -43
  354. data/spec/spec_tests/data/cmap/pool-clear-interrupt-immediately.yml +0 -49
  355. data.tar.gz.sig +0 -0
  356. metadata.gz.sig +0 -2
@@ -18,9 +18,12 @@ module Mongo
18
18
  class Server
19
19
  class AppMetadata
20
20
  # Implements the logic from the handshake spec, for deducing and
21
- # reporting the current FaaS environment in which the program is
21
+ # reporting the current environment in which the program is
22
22
  # executing.
23
23
  #
24
+ # This includes FaaS environment checks, as well as checks for the
25
+ # presence of a container (Docker) and/or orchestrator (Kubernetes).
26
+ #
24
27
  # @api private
25
28
  class Environment
26
29
  # Error class for reporting that too many discriminators were found
@@ -39,6 +42,10 @@ module Mongo
39
42
  # Error class for reporting that the value for a field is too long.
40
43
  class ValueTooLong < Mongo::Error; end
41
44
 
45
+ # The name and location of the .dockerenv file that will signal the
46
+ # presence of Docker.
47
+ DOCKERENV_PATH = '/.dockerenv'
48
+
42
49
  # This value is not explicitly specified in the spec, only implied to be
43
50
  # less than 512.
44
51
  MAXIMUM_VALUE_LENGTH = 500
@@ -102,9 +109,11 @@ module Mongo
102
109
  # if the environment contains invalid or contradictory state, it will
103
110
  # be initialized with {{name}} set to {{nil}}.
104
111
  def initialize
112
+ @fields = {}
105
113
  @error = nil
106
114
  @name = detect_environment
107
- populate_fields
115
+ populate_faas_fields
116
+ detect_container
108
117
  rescue TooManyEnvironments => e
109
118
  self.error = "too many environments detected: #{e.message}"
110
119
  rescue MissingVariable => e
@@ -115,6 +124,23 @@ module Mongo
115
124
  self.error = "value for #{e.message} is too long"
116
125
  end
117
126
 
127
+ # Queries the detected container information.
128
+ #
129
+ # @return [ Hash | nil ] the detected container information, or
130
+ # nil if no container was detected.
131
+ def container
132
+ fields[:container]
133
+ end
134
+
135
+ # Queries whether any environment information was able to be
136
+ # detected.
137
+ #
138
+ # @return [ true | false ] if any environment information was
139
+ # detected.
140
+ def present?
141
+ @name || fields.any?
142
+ end
143
+
118
144
  # Queries whether the current environment is a valid FaaS environment.
119
145
  #
120
146
  # @return [ true | false ] whether the environment is a FaaS
@@ -159,14 +185,11 @@ module Mongo
159
185
  @name == 'vercel'
160
186
  end
161
187
 
162
- # Compiles the detected environment information into a Hash. It will
163
- # always include a {{name}} key, but may include other keys as well,
164
- # depending on the detected FaaS environment. (See the handshake
165
- # spec for details.)
188
+ # Compiles the detected environment information into a Hash.
166
189
  #
167
190
  # @return [ Hash ] the detected environment information.
168
191
  def to_h
169
- fields.merge(name: name)
192
+ name ? fields.merge(name: name) : fields
170
193
  end
171
194
 
172
195
  private
@@ -192,6 +215,38 @@ module Mongo
192
215
  names.first
193
216
  end
194
217
 
218
+ # Looks for the presence of a container. Currently can detect
219
+ # Docker (by the existence of a .dockerenv file in the root
220
+ # directory) and Kubernetes (by the existence of the KUBERNETES_SERVICE_HOST
221
+ # environment variable).
222
+ def detect_container
223
+ runtime = docker_present? && 'docker'
224
+ orchestrator = kubernetes_present? && 'kubernetes'
225
+
226
+ return unless runtime || orchestrator
227
+
228
+ fields[:container] = {}
229
+ fields[:container][:runtime] = runtime if runtime
230
+ fields[:container][:orchestrator] = orchestrator if orchestrator
231
+ end
232
+
233
+ # Checks for the existence of a .dockerenv in the root directory.
234
+ def docker_present?
235
+ File.exist?(dockerenv_path)
236
+ end
237
+
238
+ # Implementing this as a method so that it can be mocked in tests, to
239
+ # test the presence or absence of Docker.
240
+ def dockerenv_path
241
+ DOCKERENV_PATH
242
+ end
243
+
244
+ # Checks for the presence of a non-empty KUBERNETES_SERVICE_HOST
245
+ # environment variable.
246
+ def kubernetes_present?
247
+ !ENV['KUBERNETES_SERVICE_HOST'].to_s.empty?
248
+ end
249
+
195
250
  # Determines whether the named environment variable exists, and (if
196
251
  # a pattern has been declared for that descriminator) whether the
197
252
  # pattern matches the value of the variable.
@@ -212,10 +267,10 @@ module Mongo
212
267
  # Extracts environment information from the current environment
213
268
  # variables, based on the detected FaaS environment. Populates the
214
269
  # {{@fields}} instance variable.
215
- def populate_fields
270
+ def populate_faas_fields
216
271
  return unless name
217
272
 
218
- @fields = FIELDS[name].each_with_object({}) do |(var, defn), fields|
273
+ FIELDS[name].each_with_object(@fields) do |(var, defn), fields|
219
274
  fields[defn[:field]] = extract_field(var, defn)
220
275
  end
221
276
  end
@@ -187,13 +187,14 @@ module Mongo
187
187
  }
188
188
  end
189
189
 
190
- # Returns the environment doc describing the current FaaS environment.
190
+ # Returns the environment doc describing the current execution
191
+ # environment.
191
192
  #
192
- # @return [ Hash | nil ] the environment doc (or nil if not in a FaaS
193
- # environment).
193
+ # @return [ Hash | nil ] the environment doc (or nil if no relevant
194
+ # environment info was detected)
194
195
  def env_doc
195
196
  env = Environment.new
196
- env.faas? ? env.to_h : nil
197
+ env.present? ? env.to_h : nil
197
198
  end
198
199
 
199
200
  def type
@@ -226,11 +226,11 @@ module Mongo
226
226
  # @return [ true ] If the connection succeeded.
227
227
  #
228
228
  # @since 2.0.0
229
- def connect!
229
+ def connect!(context = nil)
230
230
  raise_if_closed!
231
231
 
232
232
  unless @socket
233
- @socket = create_socket
233
+ @socket = create_socket(context)
234
234
  @description, @compressor = do_connect
235
235
 
236
236
  if server.load_balancer?
@@ -256,10 +256,16 @@ module Mongo
256
256
  #
257
257
  #
258
258
  # @return [ Socket ] The created socket.
259
- private def create_socket
259
+ private def create_socket(context = nil)
260
260
  add_server_diagnostics do
261
- address.socket(socket_timeout, ssl_options.merge(
262
- connection_address: address, connection_generation: generation, pipe: options[:pipe]))
261
+ opts = ssl_options.merge(
262
+ connection_address: address,
263
+ connection_generation: generation,
264
+ pipe: options[:pipe],
265
+ connect_timeout: context&.remaining_timeout_sec,
266
+ csot: !!context&.csot?
267
+ )
268
+ address.socket(socket_timeout, opts)
263
269
  end
264
270
  end
265
271
 
@@ -169,6 +169,7 @@ module Mongo
169
169
  raise Error::LintError, "Trying to deliver a message over a disconnected connection (to #{address})"
170
170
  end
171
171
  buffer = serialize(message, context)
172
+ check_timeout!(context)
172
173
  ensure_connected do |socket|
173
174
  operation_id = Monitoring.next_operation_id
174
175
  started_event = command_started(address, operation_id, message.payload,
@@ -181,9 +182,10 @@ module Mongo
181
182
  result = nil
182
183
  begin
183
184
  result = add_server_diagnostics do
184
- socket.write(buffer.to_s)
185
+ socket.write(buffer.to_s, timeout: context.remaining_timeout_sec)
185
186
  if message.replyable?
186
- Protocol::Message.deserialize(socket, max_message_size, message.request_id, options)
187
+ check_timeout!(context)
188
+ Protocol::Message.deserialize(socket, max_message_size, message.request_id, options.merge(timeout: context.remaining_timeout_sec))
187
189
  else
188
190
  nil
189
191
  end
@@ -273,6 +275,24 @@ module Mongo
273
275
 
274
276
  buffer
275
277
  end
278
+
279
+ # If timeoutMS is set for the operation context, checks whether there is
280
+ # enough time left to send the corresponding message to the server
281
+ # (remaining timeout is bigger than minimum round trip time for
282
+ # the server)
283
+ #
284
+ # @param [ Mongo::Operation::Context ] context Context of the operation.
285
+ #
286
+ # @raise [ Mongo::Error::TimeoutError ] if timeout expired or there is
287
+ # not enough time to send the message to the server.
288
+ def check_timeout!(context)
289
+ return if [nil, 0].include?(context.deadline)
290
+
291
+ time_to_execute = context.remaining_timeout_sec - server.minimum_round_trip_time
292
+ if time_to_execute <= 0
293
+ raise Mongo::Error::TimeoutError
294
+ end
295
+ end
276
296
  end
277
297
  end
278
298
  end
@@ -205,11 +205,18 @@ module Mongo
205
205
 
206
206
  # The time to wait, in seconds, for a connection to become available.
207
207
  #
208
+ # @param [ Mongo::Operation:Context | nil ] context Context of the operation
209
+ # the connection is requested for, if any.
210
+ #
208
211
  # @return [ Float ] The queue wait timeout.
209
212
  #
210
213
  # @since 2.9.0
211
- def wait_timeout
212
- @wait_timeout ||= options[:wait_timeout] || DEFAULT_WAIT_TIMEOUT
214
+ def wait_timeout(context = nil)
215
+ if context&.remaining_timeout_sec.nil?
216
+ options[:wait_timeout] || DEFAULT_WAIT_TIMEOUT
217
+ else
218
+ context&.remaining_timeout_sec
219
+ end
213
220
  end
214
221
 
215
222
  # The maximum seconds a socket can remain idle since it has been
@@ -345,6 +352,10 @@ module Mongo
345
352
  # The returned connection counts toward the pool's max size. When the
346
353
  # caller is finished using the connection, the connection should be
347
354
  # checked back in via the check_in method.
355
+ # @param [ Integer | nil ] :connection_global_id The global id for the
356
+ # connection to check out.
357
+ # @param [ Mongo::Operation:Context | nil ] :context Context of the operation
358
+ # the connection is requested for, if any.
348
359
  #
349
360
  # @return [ Mongo::Server::Connection ] The checked out connection.
350
361
  # @raise [ Error::PoolClosedError ] If the pool has been closed.
@@ -352,7 +363,7 @@ module Mongo
352
363
  # and remains so for longer than the wait timeout.
353
364
  #
354
365
  # @since 2.9.0
355
- def check_out(connection_global_id: nil)
366
+ def check_out(connection_global_id: nil, context: nil)
356
367
  check_invariants
357
368
 
358
369
  publish_cmap_event(
@@ -362,7 +373,9 @@ module Mongo
362
373
  raise_if_pool_closed!
363
374
  raise_if_pool_paused_locked!
364
375
 
365
- connection = retrieve_and_connect_connection(connection_global_id)
376
+ connection = retrieve_and_connect_connection(
377
+ connection_global_id, context
378
+ )
366
379
 
367
380
  publish_cmap_event(
368
381
  Monitoring::Event::Cmap::ConnectionCheckedOut.new(@server.address, connection.id, self),
@@ -698,10 +711,13 @@ module Mongo
698
711
  # @return [ Object ] The result of the block.
699
712
  #
700
713
  # @since 2.0.0
701
- def with_connection(connection_global_id: nil)
714
+ def with_connection(connection_global_id: nil, context: nil)
702
715
  raise_if_closed!
703
716
 
704
- connection = check_out(connection_global_id: connection_global_id)
717
+ connection = check_out(
718
+ connection_global_id: connection_global_id,
719
+ context: context
720
+ )
705
721
  yield(connection)
706
722
  rescue Error::SocketError, Error::SocketTimeoutError, Error::ConnectionPerished => e
707
723
  maybe_raise_pool_cleared!(connection, e)
@@ -975,9 +991,9 @@ module Mongo
975
991
 
976
992
  # Attempts to connect (handshake and auth) the connection. If an error is
977
993
  # encountered, closes the connection and raises the error.
978
- def connect_connection(connection)
994
+ def connect_connection(connection, context = nil)
979
995
  begin
980
- connection.connect!
996
+ connection.connect!(context)
981
997
  rescue Exception
982
998
  connection.disconnect!(reason: :error)
983
999
  raise
@@ -1242,16 +1258,18 @@ module Mongo
1242
1258
 
1243
1259
  # Retrieves a connection and connects it.
1244
1260
  #
1245
- # @param [ Integer ] connection_global_id The global id for the
1261
+ # @param [ Integer | nil ] connection_global_id The global id for the
1246
1262
  # connection to check out.
1263
+ # @param [ Mongo::Operation:Context | nil ] context Context of the operation
1264
+ # the connection is requested for, if any.
1247
1265
  #
1248
1266
  # @return [ Mongo::Server::Connection ] The checked out connection.
1249
1267
  #
1250
1268
  # @raise [ Error::PoolClosedError ] If the pool has been closed.
1251
1269
  # @raise [ Timeout::Error ] If the connection pool is at maximum size
1252
1270
  # and remains so for longer than the wait timeout.
1253
- def retrieve_and_connect_connection(connection_global_id)
1254
- deadline = Utils.monotonic_time + wait_timeout
1271
+ def retrieve_and_connect_connection(connection_global_id, context = nil)
1272
+ deadline = Utils.monotonic_time + wait_timeout(context)
1255
1273
  connection = nil
1256
1274
 
1257
1275
  @lock.synchronize do
@@ -1267,7 +1285,7 @@ module Mongo
1267
1285
  connection = wait_for_connection(connection_global_id, deadline)
1268
1286
  end
1269
1287
 
1270
- connect_or_raise(connection) unless connection.connected?
1288
+ connect_or_raise(connection, context) unless connection.connected?
1271
1289
 
1272
1290
  @lock.synchronize do
1273
1291
  @checked_out_connections << connection
@@ -1327,8 +1345,8 @@ module Mongo
1327
1345
  # cannot be connected.
1328
1346
  # This method also publish corresponding event and ensures that counters
1329
1347
  # and condition variables are updated.
1330
- def connect_or_raise(connection)
1331
- connect_connection(connection)
1348
+ def connect_or_raise(connection, context)
1349
+ connect_connection(connection, context)
1332
1350
  rescue Exception
1333
1351
  # Handshake or authentication failed
1334
1352
  @lock.synchronize do
@@ -48,6 +48,7 @@ module Mongo
48
48
  # provided by the client during findAndModify operations, requiring the
49
49
  # driver to raise client-side errors when those options are provided.
50
50
  find_and_modify_option_validation: 8,
51
+ sharded_transactions: 8,
51
52
  transactions: 7,
52
53
  scram_sha_256: 7,
53
54
  array_filters: 6,
@@ -82,7 +83,7 @@ module Mongo
82
83
  # The wire protocol versions that this version of the driver supports.
83
84
  #
84
85
  # @since 2.0.0
85
- DRIVER_WIRE_VERSIONS = (6..21).freeze
86
+ DRIVER_WIRE_VERSIONS = (6..25).freeze
86
87
 
87
88
  # Create the methods for each mapping to tell if they are supported.
88
89
  #
@@ -209,8 +209,8 @@ module Mongo
209
209
  # @param [ Hash ] config The result of the hello command.
210
210
  # @param [ Float ] average_round_trip_time The moving average time (sec) the hello
211
211
  # command took to complete.
212
- # @param [ Float ] average_round_trip_time The moving average time (sec)
213
- # the ismaster call took to complete.
212
+ # @param [ Float ] minimum_round_trip_time The minimum round trip time
213
+ # of ten last hello commands.
214
214
  # @param [ true | false ] load_balancer Whether the server is treated as
215
215
  # a load balancer.
216
216
  # @param [ true | false ] force_load_balancer Whether the server is
@@ -218,7 +218,8 @@ module Mongo
218
218
  #
219
219
  # @api private
220
220
  def initialize(address, config = {}, average_round_trip_time: nil,
221
- load_balancer: false, force_load_balancer: false
221
+ minimum_round_trip_time: 0, load_balancer: false,
222
+ force_load_balancer: false
222
223
  )
223
224
  @address = address
224
225
  @config = config
@@ -226,6 +227,7 @@ module Mongo
226
227
  @force_load_balancer = !!force_load_balancer
227
228
  @features = Features.new(wire_versions, me || @address.to_s)
228
229
  @average_round_trip_time = average_round_trip_time
230
+ @minimum_round_trip_time = minimum_round_trip_time
229
231
  @last_update_time = Time.now.freeze
230
232
  @last_update_monotime = Utils.monotonic_time
231
233
 
@@ -302,6 +304,10 @@ module Mongo
302
304
  # @return [ Float ] The moving average time the hello call took to complete.
303
305
  attr_reader :average_round_trip_time
304
306
 
307
+ # @return [ Float ] The minimum time from the ten last hello calls took
308
+ # to complete.
309
+ attr_reader :minimum_round_trip_time
310
+
305
311
  # Returns whether this server is an arbiter, per the SDAM spec.
306
312
  #
307
313
  # @example Is the server an arbiter?
@@ -723,8 +729,7 @@ module Mongo
723
729
 
724
730
  # @api private
725
731
  def ok?
726
- config[Operation::Result::OK] &&
727
- config[Operation::Result::OK] == 1 || false
732
+ config[Operation::Result::OK] == 1
728
733
  end
729
734
 
730
735
  # Get the range of supported wire versions for the server.
@@ -802,6 +807,14 @@ module Mongo
802
807
  !!(address.to_s.downcase != me.downcase if me)
803
808
  end
804
809
 
810
+ # Whether this description is from a mongocryptd server.
811
+ #
812
+ # @return [ true, false ] Whether this description is from a mongocryptd
813
+ # server.
814
+ def mongocryptd?
815
+ ok? && config['iscryptd'] == true
816
+ end
817
+
805
818
  # opTime in lastWrite subdocument of the hello response.
806
819
  #
807
820
  # @return [ BSON::Timestamp ] The timestamp.
@@ -237,8 +237,11 @@ module Mongo
237
237
  @sdam_mutex.synchronize do
238
238
  old_description = server.description
239
239
 
240
- new_description = Description.new(server.address, result,
241
- average_round_trip_time: server.round_trip_time_averager.average_round_trip_time
240
+ new_description = Description.new(
241
+ server.address,
242
+ result,
243
+ average_round_trip_time: server.round_trip_time_calculator.average_round_trip_time,
244
+ minimum_round_trip_time: server.round_trip_time_calculator.minimum_round_trip_time
242
245
  )
243
246
 
244
247
  server.cluster.run_sdam_flow(server.description, new_description, awaited: awaited, scan_error: scan_error)
@@ -306,7 +309,7 @@ module Mongo
306
309
  end
307
310
 
308
311
  if @connection
309
- result = server.round_trip_time_averager.measure do
312
+ result = server.round_trip_time_calculator.measure do
310
313
  begin
311
314
  doc = @connection.check_document
312
315
  cmd = Protocol::Query.new(
@@ -323,7 +326,7 @@ module Mongo
323
326
  else
324
327
  connection = Connection.new(server.address, options)
325
328
  connection.connect!
326
- result = server.round_trip_time_averager.measure do
329
+ result = server.round_trip_time_calculator.measure do
327
330
  connection.handshake!
328
331
  end
329
332
  @connection = connection
@@ -110,6 +110,24 @@ module Mongo
110
110
 
111
111
  private
112
112
 
113
+ # Sends the hello command to the server, then receive and deserialize
114
+ # the response.
115
+ #
116
+ # This method is extracted to be mocked in the tests.
117
+ #
118
+ # @param [ Protocol::Message ] Command that should be sent to a server
119
+ # for handshake purposes.
120
+ #
121
+ # @return [ Mongo::Protocol::Reply ] Deserialized server response.
122
+ def get_handshake_response(hello_command)
123
+ @server.round_trip_time_calculator.measure do
124
+ add_server_diagnostics do
125
+ socket.write(hello_command.serialize.to_s)
126
+ Protocol::Message.deserialize(socket, Protocol::Message::MAX_MESSAGE_SIZE)
127
+ end
128
+ end
129
+ end
130
+
113
131
  # @param [ BSON::Document | nil ] speculative_auth_doc The document to
114
132
  # provide in speculativeAuthenticate field of handshake command.
115
133
  #
@@ -131,12 +149,7 @@ module Mongo
131
149
  doc = nil
132
150
  @server.handle_handshake_failure! do
133
151
  begin
134
- response = @server.round_trip_time_averager.measure do
135
- add_server_diagnostics do
136
- socket.write(hello_command.serialize.to_s)
137
- Protocol::Message.deserialize(socket, Protocol::Message::MAX_MESSAGE_SIZE)
138
- end
139
- end
152
+ response = get_handshake_response(hello_command)
140
153
  result = Operation::Result.new([response])
141
154
  result.validate!
142
155
  doc = result.documents.first
@@ -155,7 +168,11 @@ module Mongo
155
168
  doc['serviceId'] ||= "fake:#{rand(2**32-1)+1}"
156
169
  end
157
170
 
158
- post_handshake(doc, @server.round_trip_time_averager.average_round_trip_time)
171
+ post_handshake(
172
+ doc,
173
+ @server.round_trip_time_calculator.average_round_trip_time,
174
+ @server.round_trip_time_calculator.minimum_round_trip_time
175
+ )
159
176
 
160
177
  doc
161
178
  end
@@ -205,7 +222,7 @@ module Mongo
205
222
  #
206
223
  # @return [ Server::Description ] The server description calculated from
207
224
  # the handshake response for this particular connection.
208
- def post_handshake(response, average_rtt)
225
+ def post_handshake(response, average_rtt, minimum_rtt)
209
226
  if response["ok"] == 1
210
227
  # Auth mechanism is entirely dependent on the contents of
211
228
  # hello response *for this connection*.
@@ -18,20 +18,30 @@
18
18
  module Mongo
19
19
  class Server
20
20
  # @api private
21
- class RoundTripTimeAverager
21
+ class RoundTripTimeCalculator
22
22
 
23
23
  # The weighting factor (alpha) for calculating the average moving
24
24
  # round trip time.
25
25
  RTT_WEIGHT_FACTOR = 0.2.freeze
26
26
  private_constant :RTT_WEIGHT_FACTOR
27
27
 
28
+ RTT_SAMPLES_FOR_MINIMUM = 10
29
+ private_constant :RTT_SAMPLES_FOR_MINIMUM
30
+
31
+ MIN_SAMPLES = 3
32
+ private_constant :MIN_SAMPLES
33
+
28
34
  def initialize
29
35
  @last_round_trip_time = nil
30
36
  @average_round_trip_time = nil
37
+ @minimum_round_trip_time = 0
38
+ @lock = Mutex.new
39
+ @rtts = []
31
40
  end
32
41
 
33
42
  attr_reader :last_round_trip_time
34
43
  attr_reader :average_round_trip_time
44
+ attr_reader :minimum_round_trip_time
35
45
 
36
46
  def measure
37
47
  start = Utils.monotonic_time
@@ -44,14 +54,17 @@ module Mongo
44
54
  rescue Error, Error::AuthError => exc
45
55
  # For other errors, RTT is valid.
46
56
  end
47
- last_round_trip_time = Utils.monotonic_time - start
57
+ last_rtt = Utils.monotonic_time - start
48
58
 
49
59
  # If hello fails, we need to return the last round trip time
50
60
  # because it is used in the heartbeat failed SDAM event,
51
61
  # but we must not update the round trip time recorded in the server.
52
62
  unless exc
53
- @last_round_trip_time = last_round_trip_time
54
- update_average_round_trip_time
63
+ @last_round_trip_time = last_rtt
64
+ @lock.synchronize do
65
+ update_average_round_trip_time
66
+ update_minimum_round_trip_time
67
+ end
55
68
  end
56
69
 
57
70
  if exc
@@ -61,9 +74,6 @@ module Mongo
61
74
  end
62
75
  end
63
76
 
64
- private
65
-
66
- # This method is separate for testing purposes.
67
77
  def update_average_round_trip_time
68
78
  @average_round_trip_time = if average_round_trip_time
69
79
  RTT_WEIGHT_FACTOR * last_round_trip_time + (1 - RTT_WEIGHT_FACTOR) * average_round_trip_time
@@ -71,6 +81,14 @@ module Mongo
71
81
  last_round_trip_time
72
82
  end
73
83
  end
84
+
85
+ def update_minimum_round_trip_time
86
+ @rtts.push(last_round_trip_time) unless last_round_trip_time.nil?
87
+ @minimum_round_trip_time = 0 and return if @rtts.size < MIN_SAMPLES
88
+
89
+ @rtts.shift if @rtts.size > RTT_SAMPLES_FOR_MINIMUM
90
+ @minimum_round_trip_time = @rtts.compact.min
91
+ end
74
92
  end
75
93
  end
76
94
  end
data/lib/mongo/server.rb CHANGED
@@ -80,7 +80,7 @@ module Mongo
80
80
  include Id
81
81
  end
82
82
  @scan_semaphore = DistinguishingSemaphore.new
83
- @round_trip_time_averager = RoundTripTimeAverager.new
83
+ @round_trip_time_calculator = RoundTripTimeCalculator.new
84
84
  @description = Description.new(address, {},
85
85
  load_balancer: !!@options[:load_balancer],
86
86
  force_load_balancer: force_load_balancer?,
@@ -197,6 +197,7 @@ module Mongo
197
197
  :max_message_size,
198
198
  :tags,
199
199
  :average_round_trip_time,
200
+ :minimum_round_trip_time,
200
201
  :mongos?,
201
202
  :other?,
202
203
  :primary?,
@@ -228,9 +229,9 @@ module Mongo
228
229
  # @api private
229
230
  attr_reader :scan_semaphore
230
231
 
231
- # @return [ RoundTripTimeAverager ] Round trip time averager object.
232
+ # @return [ RoundTripTimeCalculator ] Round trip time calculator object.
232
233
  # @api private
233
- attr_reader :round_trip_time_averager
234
+ attr_reader :round_trip_time_calculator
234
235
 
235
236
  # Is this server equal to another?
236
237
  #
@@ -490,8 +491,12 @@ module Mongo
490
491
  # @return [ Object ] The result of the block execution.
491
492
  #
492
493
  # @since 2.3.0
493
- def with_connection(connection_global_id: nil, &block)
494
- pool.with_connection(connection_global_id: connection_global_id, &block)
494
+ def with_connection(connection_global_id: nil, context: nil, &block)
495
+ pool.with_connection(
496
+ connection_global_id: connection_global_id,
497
+ context: context,
498
+ &block
499
+ )
495
500
  end
496
501
 
497
502
  # Handle handshake failure.
@@ -697,5 +702,5 @@ require 'mongo/server/connection'
697
702
  require 'mongo/server/connection_pool'
698
703
  require 'mongo/server/description'
699
704
  require 'mongo/server/monitor'
700
- require 'mongo/server/round_trip_time_averager'
705
+ require 'mongo/server/round_trip_time_calculator'
701
706
  require 'mongo/server/push_monitor'