mongo 2.19.1 → 2.21.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,227 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Find operation options' do
6
+ require_mri
7
+ require_no_auth
8
+ min_server_fcv '4.4'
9
+
10
+ let(:subscriber) { Mrss::EventSubscriber.new }
11
+
12
+ let(:seeds) do
13
+ [ SpecConfig.instance.addresses.first ]
14
+ end
15
+
16
+ let(:client_options) do
17
+ {}
18
+ end
19
+
20
+ let(:collection_options) do
21
+ {}
22
+ end
23
+
24
+ let(:client) do
25
+ ClientRegistry.instance.new_local_client(
26
+ seeds,
27
+ SpecConfig.instance.test_options
28
+ .merge(database: SpecConfig.instance.test_db)
29
+ .merge(client_options)
30
+ ).tap do |client|
31
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
32
+ end
33
+ end
34
+
35
+ let(:collection) do
36
+ client['find_options', collection_options]
37
+ end
38
+
39
+ let(:find_command) do
40
+ subscriber.started_events.find { |cmd| cmd.command_name == 'find' }
41
+ end
42
+
43
+ let(:should_create_collection) { true }
44
+
45
+ before do
46
+ client['find_options'].drop
47
+ collection.create if should_create_collection
48
+ collection.insert_many([ { a: 1 }, { a: 2 }, { a: 3 } ])
49
+ end
50
+
51
+ describe 'collation' do
52
+ let(:client_options) do
53
+ {}
54
+ end
55
+
56
+ let(:collation) do
57
+ { 'locale' => 'en_US' }
58
+ end
59
+
60
+ context 'when defined on the collection' do
61
+ let(:collection_options) do
62
+ { collation: collation }
63
+ end
64
+
65
+ it 'uses the collation defined on the collection' do
66
+ collection.find.to_a
67
+ expect(find_command.command['collation']).to be_nil
68
+ end
69
+ end
70
+
71
+ context 'when defined on the operation' do
72
+ let(:collection_options) do
73
+ {}
74
+ end
75
+
76
+ it 'uses the collation defined on the collection' do
77
+ collection.find({}, collation: collation).to_a
78
+ expect(find_command.command['collation']).to eq(collation)
79
+ end
80
+ end
81
+
82
+ context 'when defined on both collection and operation' do
83
+ let(:collection_options) do
84
+ { 'locale' => 'de_AT' }
85
+ end
86
+
87
+ let(:should_create_collection) { false }
88
+
89
+ it 'uses the collation defined on the collection' do
90
+ collection.find({}, collation: collation).to_a
91
+ expect(find_command.command['collation']).to eq(collation)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe 'read concern' do
97
+ context 'when defined on the client' do
98
+ let(:client_options) do
99
+ { read_concern: { level: :local } }
100
+ end
101
+
102
+ let(:collection_options) do
103
+ {}
104
+ end
105
+
106
+ it 'uses the read concern defined on the client' do
107
+ collection.find.to_a
108
+ expect(find_command.command['readConcern']).to eq('level' => 'local')
109
+ end
110
+
111
+ context 'when defined on the collection' do
112
+ let(:collection_options) do
113
+ { read_concern: { level: :majority } }
114
+ end
115
+
116
+ it 'uses the read concern defined on the collection' do
117
+ collection.find.to_a
118
+ expect(find_command.command['readConcern']).to eq('level' => 'majority')
119
+ end
120
+
121
+ context 'when defined on the operation' do
122
+ let(:operation_read_concern) do
123
+ { level: :available }
124
+ end
125
+
126
+ it 'uses the read concern defined on the operation' do
127
+ collection.find({}, read_concern: operation_read_concern).to_a
128
+ expect(find_command.command['readConcern']).to eq('level' => 'available')
129
+ end
130
+ end
131
+ end
132
+
133
+ context 'when defined on the operation' do
134
+ let(:collection_options) do
135
+ {}
136
+ end
137
+
138
+ let(:operation_read_concern) do
139
+ { level: :available }
140
+ end
141
+
142
+ it 'uses the read concern defined on the operation' do
143
+ collection.find({}, read_concern: operation_read_concern).to_a
144
+ expect(find_command.command['readConcern']).to eq('level' => 'available')
145
+ end
146
+ end
147
+ end
148
+
149
+ context 'when defined on the collection' do
150
+ let(:client_options) do
151
+ {}
152
+ end
153
+
154
+ let(:collection_options) do
155
+ { read_concern: { level: :majority } }
156
+ end
157
+
158
+ it 'uses the read concern defined on the collection' do
159
+ collection.find.to_a
160
+ expect(find_command.command['readConcern']).to eq('level' => 'majority')
161
+ end
162
+
163
+ context 'when defined on the operation' do
164
+ let(:operation_read_concern) do
165
+ { level: :available }
166
+ end
167
+
168
+ it 'uses the read concern defined on the operation' do
169
+ collection.find({}, read_concern: operation_read_concern).to_a
170
+ expect(find_command.command['readConcern']).to eq('level' => 'available')
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ describe 'read preference' do
177
+ require_topology :replica_set
178
+
179
+ context 'when defined on the client' do
180
+ let(:client_options) do
181
+ { read: { mode: :secondary } }
182
+ end
183
+
184
+ let(:collection_options) do
185
+ {}
186
+ end
187
+
188
+ it 'uses the read preference defined on the client' do
189
+ collection.find.to_a
190
+ expect(find_command.command['$readPreference']).to eq('mode' => 'secondary')
191
+ end
192
+
193
+ context 'when defined on the collection' do
194
+ let(:collection_options) do
195
+ { read: { mode: :secondary_preferred } }
196
+ end
197
+
198
+ it 'uses the read concern defined on the collection' do
199
+ collection.find.to_a
200
+ expect(find_command.command['$readPreference']).to eq('mode' => 'secondaryPreferred')
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ describe 'cursor type' do
207
+ let(:collection_options) do
208
+ { capped: true, size: 1000 }
209
+ end
210
+
211
+ context 'when cursor type is :tailable' do
212
+ it 'sets the cursor type to tailable' do
213
+ collection.find({}, cursor_type: :tailable).first
214
+ expect(find_command.command['tailable']).to be true
215
+ expect(find_command.command['awaitData']).to be_falsey
216
+ end
217
+ end
218
+
219
+ context 'when cursor type is :tailable_await' do
220
+ it 'sets the cursor type to tailable' do
221
+ collection.find({}, cursor_type: :tailable_await).first
222
+ expect(find_command.command['tailable']).to be true
223
+ expect(find_command.command['awaitData']).to be true
224
+ end
225
+ end
226
+ end
227
+ end
@@ -17,7 +17,7 @@ describe 'OperationFailure code' do
17
17
  collection.insert_one(_id: 1)
18
18
  collection.insert_one(_id: 1)
19
19
  fail('Should have raised')
20
- rescue Mongo::Error::OperationFailure => e
20
+ rescue Mongo::Error::OperationFailure::Family => e
21
21
  expect(e.code).to eq(11000)
22
22
  # 4.0 and 4.2 sharded clusters set code name.
23
23
  # 4.0 and 4.2 replica sets and standalones do not,
@@ -22,7 +22,7 @@ describe 'OperationFailure message' do
22
22
  begin
23
23
  client.command(bogus_command: nil)
24
24
  fail('Should have raised')
25
- rescue Mongo::Error::OperationFailure => e
25
+ rescue Mongo::Error::OperationFailure::Family => e
26
26
  e.code_name.should == 'CommandNotFound'
27
27
  e.message.should =~ %r,\A\[59:CommandNotFound\]: no such (?:command|cmd): '?bogus_command'?,
28
28
  end
@@ -36,7 +36,7 @@ describe 'OperationFailure message' do
36
36
  begin
37
37
  client.command(bogus_command: nil)
38
38
  fail('Should have raised')
39
- rescue Mongo::Error::OperationFailure => e
39
+ rescue Mongo::Error::OperationFailure::Family => e
40
40
  e.code_name.should be nil
41
41
  e.message.should =~ %r,\A\[59\]: no such (?:command|cmd): '?bogus_command'?,
42
42
  end
@@ -53,7 +53,7 @@ describe 'OperationFailure message' do
53
53
  collection.insert_one(_id: 1)
54
54
  collection.insert_one(_id: 1)
55
55
  fail('Should have raised')
56
- rescue Mongo::Error::OperationFailure => e
56
+ rescue Mongo::Error::OperationFailure::Family => e
57
57
  e.code_name.should be nil
58
58
  e.message.should =~ %r,\A\[11000\]: (?:insertDocument :: caused by :: 11000 )?E11000 duplicate key error (?:collection|index):,
59
59
  end
@@ -83,7 +83,7 @@ describe 'Failing retryable operations' do
83
83
 
84
84
  begin
85
85
  collection.find(a: 1).to_a
86
- rescue Mongo::Error::OperationFailure => exception
86
+ rescue Mongo::Error::OperationFailure::Family => exception
87
87
  else
88
88
  fail('Expected operation to fail')
89
89
  end
@@ -128,7 +128,7 @@ describe 'Failing retryable operations' do
128
128
 
129
129
  begin
130
130
  collection.insert_one(a: 1)
131
- rescue Mongo::Error::OperationFailure => exception
131
+ rescue Mongo::Error::OperationFailure::Family => exception
132
132
  else
133
133
  fail('Expected operation to fail')
134
134
  end
@@ -4,6 +4,7 @@
4
4
  require 'spec_helper'
5
5
 
6
6
  describe 'Retryable reads errors tests' do
7
+ retry_test
7
8
 
8
9
  let(:client) { authorized_client.with(options.merge(retry_reads: true)) }
9
10
 
@@ -20,14 +21,14 @@ describe 'Retryable reads errors tests' do
20
21
 
21
22
  let(:failpoint) do
22
23
  {
23
- configureFailPoint: "failCommand",
24
- mode: { times: 1 },
25
- data: {
26
- failCommands: [ "find" ],
27
- errorCode: 91,
28
- blockConnection: true,
29
- blockTimeMS: 1000
30
- }
24
+ configureFailPoint: "failCommand",
25
+ mode: { times: 1 },
26
+ data: {
27
+ failCommands: [ "find" ],
28
+ errorCode: 91,
29
+ blockConnection: true,
30
+ blockTimeMS: 1000
31
+ }
31
32
  }
32
33
  end
33
34
 
@@ -73,31 +74,42 @@ describe 'Retryable reads errors tests' do
73
74
  client.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)
74
75
  end
75
76
 
76
- it "retries on PoolClearedError" do
77
- # After the first find fails, the pool is paused and retry is triggered.
78
- # Now, a race is started between the second find acquiring a connection,
79
- # and the first retrying the read. Now, retry reads cause the cluster to
80
- # be rescanned and the pool to be unpaused, allowing the second checkout
81
- # to succeed (when it should fail). Therefore we want the second find's
82
- # check out to win the race. This gives the check out a little head start.
83
- allow_any_instance_of(Mongo::Server::ConnectionPool).to receive(:ready).and_wrap_original do |m, *args, &block|
84
- ::Utils.wait_for_condition(5) do
85
- # check_out_results should contain:
86
- # - find1 connection check out successful
87
- # - pool cleared
88
- # - find2 connection check out failed
89
- # We wait here for the third event to happen before we ready the pool.
90
- cmap_events.select do |e|
91
- event_types.include?(e.class)
92
- end.length >= 3
77
+ shared_examples_for 'retries on PoolClearedError' do
78
+ it "retries on PoolClearedError" do
79
+ # After the first find fails, the pool is paused and retry is triggered.
80
+ # Now, a race is started between the second find acquiring a connection,
81
+ # and the first retrying the read. Now, retry reads cause the cluster to
82
+ # be rescanned and the pool to be unpaused, allowing the second checkout
83
+ # to succeed (when it should fail). Therefore we want the second find's
84
+ # check out to win the race. This gives the check out a little head start.
85
+ allow_any_instance_of(Mongo::Server::ConnectionPool).to receive(:ready).and_wrap_original do |m, *args, &block|
86
+ ::Utils.wait_for_condition(5) do
87
+ # check_out_results should contain:
88
+ # - find1 connection check out successful
89
+ # - pool cleared
90
+ # - find2 connection check out failed
91
+ # We wait here for the third event to happen before we ready the pool.
92
+ cmap_events.select do |e|
93
+ event_types.include?(e.class)
94
+ end.length >= 3
95
+ end
96
+ m.call(*args, &block)
93
97
  end
94
- m.call(*args, &block)
98
+ threads.map(&:join)
99
+ expect(check_out_results[0]).to be_a(Mongo::Monitoring::Event::Cmap::ConnectionCheckedOut)
100
+ expect(check_out_results[1]).to be_a(Mongo::Monitoring::Event::Cmap::PoolCleared)
101
+ expect(check_out_results[2]).to be_a(Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed)
102
+ expect(find_events.length).to eq(3)
95
103
  end
96
- threads.map(&:join)
97
- expect(check_out_results[0]).to be_a(Mongo::Monitoring::Event::Cmap::ConnectionCheckedOut)
98
- expect(check_out_results[1]).to be_a(Mongo::Monitoring::Event::Cmap::PoolCleared)
99
- expect(check_out_results[2]).to be_a(Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed)
100
- expect(find_events.length).to eq(3)
104
+ end
105
+
106
+ it_behaves_like 'retries on PoolClearedError'
107
+
108
+ context 'legacy read retries' do
109
+
110
+ let(:client) { authorized_client.with(options.merge(retry_reads: false, max_read_retries: 1)) }
111
+
112
+ it_behaves_like 'retries on PoolClearedError'
101
113
  end
102
114
 
103
115
  after do
@@ -107,4 +119,157 @@ describe 'Retryable reads errors tests' do
107
119
  })
108
120
  end
109
121
  end
122
+
123
+ context 'Retries in a sharded cluster' do
124
+ require_topology :sharded
125
+ min_server_version '4.2'
126
+ require_no_auth
127
+
128
+ let(:subscriber) { Mrss::EventSubscriber.new }
129
+
130
+ let(:find_started_events) do
131
+ subscriber.started_events.select { |e| e.command_name == "find" }
132
+ end
133
+
134
+ let(:find_failed_events) do
135
+ subscriber.failed_events.select { |e| e.command_name == "find" }
136
+ end
137
+
138
+ let(:find_succeeded_events) do
139
+ subscriber.succeeded_events.select { |e| e.command_name == "find" }
140
+ end
141
+
142
+ context 'when another mongos is available' do
143
+
144
+ let(:first_mongos) do
145
+ Mongo::Client.new(
146
+ [SpecConfig.instance.addresses.first],
147
+ direct_connection: true,
148
+ database: 'admin'
149
+ )
150
+ end
151
+
152
+ let(:second_mongos) do
153
+ Mongo::Client.new(
154
+ [SpecConfig.instance.addresses.last],
155
+ direct_connection: false,
156
+ database: 'admin'
157
+ )
158
+ end
159
+
160
+ let(:client) do
161
+ new_local_client(
162
+ [
163
+ SpecConfig.instance.addresses.first,
164
+ SpecConfig.instance.addresses.last,
165
+ ],
166
+ SpecConfig.instance.test_options.merge(retry_reads: true)
167
+ )
168
+ end
169
+
170
+ let(:expected_servers) do
171
+ [
172
+ SpecConfig.instance.addresses.first.to_s,
173
+ SpecConfig.instance.addresses.last.to_s
174
+ ].sort
175
+ end
176
+
177
+ before do
178
+ skip 'This test requires at least two mongos' if SpecConfig.instance.addresses.length < 2
179
+
180
+ first_mongos.database.command(
181
+ configureFailPoint: 'failCommand',
182
+ mode: { times: 1 },
183
+ data: {
184
+ failCommands: %w(find),
185
+ closeConnection: false,
186
+ errorCode: 6
187
+ }
188
+ )
189
+
190
+ second_mongos.database.command(
191
+ configureFailPoint: 'failCommand',
192
+ mode: { times: 1 },
193
+ data: {
194
+ failCommands: %w(find),
195
+ closeConnection: false,
196
+ errorCode: 6
197
+ }
198
+ )
199
+ end
200
+
201
+ after do
202
+ [first_mongos, second_mongos].each do |admin_client|
203
+ admin_client.database.command(
204
+ configureFailPoint: 'failCommand',
205
+ mode: 'off'
206
+ )
207
+ admin_client.close
208
+ end
209
+ client.close
210
+ end
211
+
212
+ it 'retries on different mongos' do
213
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
214
+ expect { collection.find.first }.to raise_error(Mongo::Error::OperationFailure)
215
+ expect(find_started_events.map { |e| e.address.to_s }.sort).to eq(expected_servers)
216
+ expect(find_failed_events.map { |e| e.address.to_s }.sort).to eq(expected_servers)
217
+ end
218
+ end
219
+
220
+ context 'when no other mongos is available' do
221
+ let(:mongos) do
222
+ Mongo::Client.new(
223
+ [SpecConfig.instance.addresses.first],
224
+ direct_connection: true,
225
+ database: 'admin'
226
+ )
227
+ end
228
+
229
+ let(:client) do
230
+ new_local_client(
231
+ [
232
+ SpecConfig.instance.addresses.first
233
+ ],
234
+ SpecConfig.instance.test_options.merge(retry_reads: true)
235
+ )
236
+ end
237
+
238
+ before do
239
+ mongos.database.command(
240
+ configureFailPoint: 'failCommand',
241
+ mode: { times: 1 },
242
+ data: {
243
+ failCommands: %w(find),
244
+ closeConnection: false,
245
+ errorCode: 6
246
+ }
247
+ )
248
+ end
249
+
250
+ after do
251
+ mongos.database.command(
252
+ configureFailPoint: 'failCommand',
253
+ mode: 'off'
254
+ )
255
+ mongos.close
256
+ client.close
257
+ end
258
+
259
+ it 'retries on the same mongos' do
260
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
261
+ expect { collection.find.first }.not_to raise_error
262
+ expect(find_started_events.map { |e| e.address.to_s }.sort).to eq([
263
+ SpecConfig.instance.addresses.first.to_s,
264
+ SpecConfig.instance.addresses.first.to_s
265
+ ])
266
+ expect(find_failed_events.map { |e| e.address.to_s }.sort).to eq([
267
+ SpecConfig.instance.addresses.first.to_s
268
+ ])
269
+ expect(find_succeeded_events.map { |e| e.address.to_s }.sort).to eq([
270
+ SpecConfig.instance.addresses.first.to_s
271
+ ])
272
+ end
273
+ end
274
+ end
110
275
  end
@@ -189,4 +189,160 @@ describe 'Retryable writes errors tests' do
189
189
  })
190
190
  end
191
191
  end
192
+
193
+ context 'Retries in a sharded cluster' do
194
+ require_topology :sharded
195
+ min_server_version '4.2'
196
+ require_no_auth
197
+
198
+ let(:subscriber) { Mrss::EventSubscriber.new }
199
+
200
+ let(:insert_started_events) do
201
+ subscriber.started_events.select { |e| e.command_name == "insert" }
202
+ end
203
+
204
+ let(:insert_failed_events) do
205
+ subscriber.failed_events.select { |e| e.command_name == "insert" }
206
+ end
207
+
208
+ let(:insert_succeeded_events) do
209
+ subscriber.succeeded_events.select { |e| e.command_name == "insert" }
210
+ end
211
+
212
+ context 'when another mongos is available' do
213
+
214
+ let(:first_mongos) do
215
+ Mongo::Client.new(
216
+ [SpecConfig.instance.addresses.first],
217
+ direct_connection: true,
218
+ database: 'admin'
219
+ )
220
+ end
221
+
222
+ let(:second_mongos) do
223
+ Mongo::Client.new(
224
+ [SpecConfig.instance.addresses.last],
225
+ direct_connection: false,
226
+ database: 'admin'
227
+ )
228
+ end
229
+
230
+ let(:client) do
231
+ new_local_client(
232
+ [
233
+ SpecConfig.instance.addresses.first,
234
+ SpecConfig.instance.addresses.last,
235
+ ],
236
+ SpecConfig.instance.test_options.merge(retry_writes: true)
237
+ )
238
+ end
239
+
240
+ let(:expected_servers) do
241
+ [
242
+ SpecConfig.instance.addresses.first.to_s,
243
+ SpecConfig.instance.addresses.last.to_s
244
+ ].sort
245
+ end
246
+
247
+ before do
248
+ skip 'This test requires at least two mongos' if SpecConfig.instance.addresses.length < 2
249
+
250
+ first_mongos.database.command(
251
+ configureFailPoint: 'failCommand',
252
+ mode: { times: 1 },
253
+ data: {
254
+ failCommands: %w(insert),
255
+ closeConnection: false,
256
+ errorCode: 6,
257
+ errorLabels: ['RetryableWriteError']
258
+ }
259
+ )
260
+
261
+ second_mongos.database.command(
262
+ configureFailPoint: 'failCommand',
263
+ mode: { times: 1 },
264
+ data: {
265
+ failCommands: %w(insert),
266
+ closeConnection: false,
267
+ errorCode: 6,
268
+ errorLabels: ['RetryableWriteError']
269
+ }
270
+ )
271
+ end
272
+
273
+ after do
274
+ [first_mongos, second_mongos].each do |admin_client|
275
+ admin_client.database.command(
276
+ configureFailPoint: 'failCommand',
277
+ mode: 'off'
278
+ )
279
+ admin_client.close
280
+ end
281
+ client.close
282
+ end
283
+
284
+ it 'retries on different mongos' do
285
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
286
+ expect { collection.insert_one(x: 1) }.to raise_error(Mongo::Error::OperationFailure)
287
+ expect(insert_started_events.map { |e| e.address.to_s }.sort).to eq(expected_servers)
288
+ expect(insert_failed_events.map { |e| e.address.to_s }.sort).to eq(expected_servers)
289
+ end
290
+ end
291
+
292
+ context 'when no other mongos is available' do
293
+ let(:mongos) do
294
+ Mongo::Client.new(
295
+ [SpecConfig.instance.addresses.first],
296
+ direct_connection: true,
297
+ database: 'admin'
298
+ )
299
+ end
300
+
301
+ let(:client) do
302
+ new_local_client(
303
+ [
304
+ SpecConfig.instance.addresses.first
305
+ ],
306
+ SpecConfig.instance.test_options.merge(retry_writes: true)
307
+ )
308
+ end
309
+
310
+ before do
311
+ mongos.database.command(
312
+ configureFailPoint: 'failCommand',
313
+ mode: { times: 1 },
314
+ data: {
315
+ failCommands: %w(insert),
316
+ closeConnection: false,
317
+ errorCode: 6,
318
+ errorLabels: ['RetryableWriteError']
319
+ }
320
+ )
321
+ end
322
+
323
+ after do
324
+ mongos.database.command(
325
+ configureFailPoint: 'failCommand',
326
+ mode: 'off'
327
+ )
328
+ mongos.close
329
+ client.close
330
+ end
331
+
332
+ it 'retries on the same mongos' do
333
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
334
+ expect { collection.insert_one(x: 1) }.not_to raise_error
335
+ expect(insert_started_events.map { |e| e.address.to_s }.sort).to eq([
336
+ SpecConfig.instance.addresses.first.to_s,
337
+ SpecConfig.instance.addresses.first.to_s
338
+ ])
339
+ expect(insert_failed_events.map { |e| e.address.to_s }.sort).to eq([
340
+ SpecConfig.instance.addresses.first.to_s
341
+ ])
342
+ expect(insert_succeeded_events.map { |e| e.address.to_s }.sort).to eq([
343
+ SpecConfig.instance.addresses.first.to_s
344
+ ])
345
+ end
346
+ end
347
+ end
192
348
  end