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
@@ -15,6 +15,8 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+ require 'mongo/collection/view/aggregation/behavior'
19
+
18
20
  module Mongo
19
21
  class Collection
20
22
  class View
@@ -23,46 +25,11 @@ module Mongo
23
25
  #
24
26
  # @since 2.0.0
25
27
  class Aggregation
26
- extend Forwardable
27
- include Enumerable
28
- include Immutable
29
- include Iterable
30
- include Explainable
31
- include Loggable
32
- include Retryable
28
+ include Behavior
33
29
 
34
- # @return [ View ] view The collection view.
35
- attr_reader :view
36
30
  # @return [ Array<Hash> ] pipeline The aggregation pipeline.
37
31
  attr_reader :pipeline
38
32
 
39
- # Delegate necessary operations to the view.
40
- def_delegators :view, :collection, :read, :cluster
41
-
42
- # Delegate necessary operations to the collection.
43
- def_delegators :collection, :database, :client
44
-
45
- # The reroute message.
46
- #
47
- # @since 2.1.0
48
- # @deprecated
49
- REROUTE = 'Rerouting the Aggregation operation to the primary server.'.freeze
50
-
51
- # Set to true if disk usage is allowed during the aggregation.
52
- #
53
- # @example Set disk usage flag.
54
- # aggregation.allow_disk_use(true)
55
- #
56
- # @param [ true, false ] value The flag value.
57
- #
58
- # @return [ true, false, Aggregation ] The aggregation if a value was
59
- # set or the value if used as a getter.
60
- #
61
- # @since 2.0.0
62
- def allow_disk_use(value = nil)
63
- configure(:allow_disk_use, value)
64
- end
65
-
66
33
  # Initialize the aggregation for the provided collection view, pipeline
67
34
  # and options.
68
35
  #
@@ -86,59 +53,29 @@ module Mongo
86
53
  # @option options [ Hash ] :let Mapping of variables to use in the pipeline.
87
54
  # See the server documentation for details.
88
55
  # @option options [ Integer ] :max_time_ms The maximum amount of time in
89
- # milliseconds to allow the aggregation to run.
90
- # @option options [ true, false ] :use_cursor Indicates whether the command
91
- # will request that the server provide results using a cursor. Note that
92
- # as of server version 3.6, aggregations always provide results using a
93
- # cursor and this option is therefore not valid.
56
+ # milliseconds to allow the aggregation to run. This option is deprecated, use
57
+ # :timeout_ms instead.
94
58
  # @option options [ Session ] :session The session to use.
59
+ # @option options [ :cursor_lifetime | :iteration ] :timeout_mode How to interpret
60
+ # :timeout_ms (whether it applies to the lifetime of the cursor, or per
61
+ # iteration).
62
+ # @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
63
+ # Must be a non-negative integer. An explicit value of 0 means infinite.
64
+ # The default value is unset which means the value is inherited from
65
+ # the collection or the database or the client.
95
66
  #
96
67
  # @since 2.0.0
97
68
  def initialize(view, pipeline, options = {})
98
- @view = view
99
- @pipeline = pipeline.dup
100
- unless Mongo.broken_view_aggregate || view.filter.empty?
101
- @pipeline.unshift(:$match => view.filter)
69
+ perform_setup(view, options) do
70
+ @pipeline = pipeline.dup
71
+ unless Mongo.broken_view_aggregate || view.filter.empty?
72
+ @pipeline.unshift(:$match => view.filter)
73
+ end
102
74
  end
103
- @options = BSON::Document.new(options).freeze
104
- end
105
-
106
- # Get the explain plan for the aggregation.
107
- #
108
- # @example Get the explain plan for the aggregation.
109
- # aggregation.explain
110
- #
111
- # @return [ Hash ] The explain plan.
112
- #
113
- # @since 2.0.0
114
- def explain
115
- self.class.new(view, pipeline, options.merge(explain: true)).first
116
- end
117
-
118
- # Whether this aggregation will write its result to a database collection.
119
- #
120
- # @return [ Boolean ] Whether the aggregation will write its result
121
- # to a collection.
122
- #
123
- # @api private
124
- def write?
125
- pipeline.any? { |op| op.key?('$out') || op.key?(:$out) || op.key?('$merge') || op.key?(:$merge) }
126
75
  end
127
76
 
128
77
  private
129
78
 
130
- def server_selector
131
- @view.send(:server_selector)
132
- end
133
-
134
- def aggregate_spec(session, read_preference)
135
- Builder::Aggregation.new(
136
- pipeline,
137
- view,
138
- options.merge(session: session, read_preference: read_preference)
139
- ).specification
140
- end
141
-
142
79
  def new(options)
143
80
  Aggregation.new(view, pipeline, options)
144
81
  end
@@ -180,32 +117,29 @@ module Mongo
180
117
 
181
118
  end
182
119
 
183
- def send_initial_query(server, session)
184
- server.with_connection do |connection|
120
+ def send_initial_query(server, context)
121
+ if server.load_balancer?
122
+ # Connection will be checked in when cursor is drained.
123
+ connection = server.pool.check_out(context: context)
185
124
  initial_query_op(
186
- session,
125
+ context.session,
187
126
  effective_read_preference(connection)
188
127
  ).execute_with_connection(
189
128
  connection,
190
- context: Operation::Context.new(client: client, session: session)
129
+ context: context
191
130
  )
131
+ else
132
+ server.with_connection do |connection|
133
+ initial_query_op(
134
+ context.session,
135
+ effective_read_preference(connection)
136
+ ).execute_with_connection(
137
+ connection,
138
+ context: context
139
+ )
140
+ end
192
141
  end
193
142
  end
194
-
195
- # Skip, sort, limit, projection are specified as pipeline stages
196
- # rather than as options.
197
- def cache_options
198
- {
199
- namespace: collection.namespace,
200
- selector: pipeline,
201
- read_concern: view.read_concern,
202
- read_preference: view.read_preference,
203
- collation: options[:collation],
204
- # Aggregations can read documents from more than one collection,
205
- # so they will be cleared on every write operation.
206
- multi_collection: true,
207
- }
208
- end
209
143
  end
210
144
  end
211
145
  end
@@ -113,17 +113,11 @@ module Mongo
113
113
  command[:readConcern] = Options::Mapper.transform_values_to_strings(
114
114
  read_concern)
115
115
  end
116
- command[:cursor] = cursor if cursor
116
+ command[:cursor] = batch_size_doc
117
117
  command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
118
118
  command
119
119
  end
120
120
 
121
- def cursor
122
- if options[:use_cursor] == true || options[:use_cursor].nil?
123
- batch_size_doc
124
- end
125
- end
126
-
127
121
  def batch_size_doc
128
122
  value = options[:batch_size] || view.batch_size
129
123
  if value == 0 && write?
@@ -15,6 +15,7 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+ require 'mongo/collection/view/aggregation/behavior'
18
19
  require 'mongo/collection/view/change_stream/retryable'
19
20
 
20
21
  module Mongo
@@ -35,7 +36,8 @@ module Mongo
35
36
  #
36
37
  #
37
38
  # @since 2.5.0
38
- class ChangeStream < Aggregation
39
+ class ChangeStream
40
+ include Aggregation::Behavior
39
41
  include Retryable
40
42
 
41
43
  # @return [ String ] The fullDocument option default value.
@@ -60,6 +62,10 @@ module Mongo
60
62
  # @since 2.5.0
61
63
  attr_reader :options
62
64
 
65
+ # @return [ Cursor ] the underlying cursor for this operation
66
+ # @api private
67
+ attr_reader :cursor
68
+
63
69
  # Initialize the change stream for the provided collection view, pipeline
64
70
  # and options.
65
71
  #
@@ -125,11 +131,13 @@ module Mongo
125
131
  #
126
132
  # @since 2.5.0
127
133
  def initialize(view, pipeline, changes_for, options = {})
128
- @view = view
129
- @changes_for = changes_for
130
- @change_stream_filters = pipeline && pipeline.dup
131
- @options = options && options.dup.freeze
132
- @start_after = @options[:start_after]
134
+ # change stream cursors can only be :iterable, so we don't allow
135
+ # timeout_mode to be specified.
136
+ perform_setup(view, options, forbid: %i[ timeout_mode ]) do
137
+ @changes_for = changes_for
138
+ @change_stream_filters = pipeline && pipeline.dup
139
+ @start_after = @options[:start_after]
140
+ end
133
141
 
134
142
  # The resume token tracked by the change stream, used only
135
143
  # when there is no cursor, or no cursor resume token
@@ -181,24 +189,30 @@ module Mongo
181
189
  # @return [ BSON::Document | nil ] A change stream document.
182
190
  # @since 2.6.0
183
191
  def try_next
192
+ recreate_cursor! if @timed_out
193
+
184
194
  raise StopIteration.new if closed?
195
+
185
196
  begin
186
197
  doc = @cursor.try_next
187
198
  rescue Mongo::Error => e
188
- if !e.change_stream_resumable?
189
- raise
190
- end
191
-
192
- # Rerun initial aggregation.
193
- # Any errors here will stop iteration and break out of this
194
- # method.
199
+ # "If a next call fails with a timeout error, drivers MUST NOT
200
+ # invalidate the change stream. The subsequent next call MUST
201
+ # perform a resume attempt to establish a new change stream on the
202
+ # server..."
203
+ #
204
+ # However, SocketTimeoutErrors are TimeoutErrors, but are also
205
+ # change-stream-resumable. To preserve existing (specified) behavior,
206
+ # We only count timeouts when the error is not also
207
+ # change-stream-resumable.
208
+ @timed_out = e.is_a?(Mongo::Error::TimeoutError) && !e.change_stream_resumable?
209
+
210
+ raise unless @timed_out || e.change_stream_resumable?
195
211
 
196
- # Save cursor's resume token so we can use it
197
- # to create a new cursor
198
212
  @resume_token = @cursor.resume_token
213
+ raise e if @timed_out
199
214
 
200
- close
201
- create_cursor!
215
+ recreate_cursor!(@cursor.context)
202
216
  retry
203
217
  end
204
218
 
@@ -231,14 +245,17 @@ module Mongo
231
245
  # This method ignores any errors that occur when closing the
232
246
  # server-side cursor.
233
247
  #
248
+ # @params [ Hash ] opts Options to be passed to the cursor close
249
+ # command.
250
+ #
234
251
  # @return [ nil ] Always nil.
235
252
  #
236
253
  # @since 2.5.0
237
- def close
254
+ def close(opts = {})
238
255
  unless closed?
239
256
  begin
240
- @cursor.close
241
- rescue Error::OperationFailure, Error::SocketError, Error::SocketTimeoutError, Error::MissingConnection
257
+ @cursor.close(opts)
258
+ rescue Error::OperationFailure::Family, Error::SocketError, Error::SocketTimeoutError, Error::MissingConnection
242
259
  # ignore
243
260
  end
244
261
  @cursor = nil
@@ -284,6 +301,28 @@ module Mongo
284
301
  cursor_resume_token || @resume_token
285
302
  end
286
303
 
304
+ # "change streams are an abstraction around tailable-awaitData cursors..."
305
+ #
306
+ # @return :tailable_await
307
+ def cursor_type
308
+ :tailable_await
309
+ end
310
+
311
+ # "change streams...implicitly use ITERATION mode"
312
+ #
313
+ # @return :iteration
314
+ def timeout_mode
315
+ :iteration
316
+ end
317
+
318
+ # Returns the value of the max_await_time_ms option that was
319
+ # passed to this change stream.
320
+ #
321
+ # @return [ Integer | nil ] the max_await_time_ms value
322
+ def max_await_time_ms
323
+ options[:max_await_time_ms]
324
+ end
325
+
287
326
  private
288
327
 
289
328
  def for_cluster?
@@ -298,19 +337,23 @@ module Mongo
298
337
  !for_cluster? && !for_database?
299
338
  end
300
339
 
301
- def create_cursor!
340
+ def create_cursor!(timeout_ms = nil)
302
341
  # clear the cache because we may get a newer or an older server
303
342
  # (rolling upgrades)
304
343
  @start_at_operation_time_supported = nil
305
344
 
306
- session = client.send(:get_session, @options)
345
+ session = client.get_session(@options)
346
+ context = Operation::Context.new(client: client, session: session, view: self, operation_timeouts: timeout_ms ? { operation_timeout_ms: timeout_ms } : operation_timeouts)
347
+
307
348
  start_at_operation_time = nil
308
349
  start_at_operation_time_supported = nil
309
- @cursor = read_with_retry_cursor(session, server_selector, view) do |server|
350
+
351
+ @cursor = read_with_retry_cursor(session, server_selector, self, context: context) do |server|
310
352
  server.with_connection do |connection|
311
353
  start_at_operation_time_supported = connection.description.server_version_gte?('4.0')
312
354
 
313
- result = send_initial_query(connection, session)
355
+ result = send_initial_query(connection, context)
356
+
314
357
  if doc = result.replies.first && result.replies.first.documents.first
315
358
  start_at_operation_time = doc['operationTime']
316
359
  else
@@ -324,6 +367,7 @@ module Mongo
324
367
  result
325
368
  end
326
369
  end
370
+
327
371
  @start_at_operation_time = start_at_operation_time
328
372
  @start_at_operation_time_supported = start_at_operation_time_supported
329
373
  end
@@ -390,11 +434,11 @@ module Mongo
390
434
  end
391
435
  end
392
436
 
393
- def send_initial_query(connection, session)
394
- initial_query_op(session, view.read_preference)
437
+ def send_initial_query(connection, context)
438
+ initial_query_op(context.session, view.read_preference)
395
439
  .execute_with_connection(
396
440
  connection,
397
- context: Operation::Context.new(client: client, session: session),
441
+ context: context,
398
442
  )
399
443
  end
400
444
 
@@ -412,6 +456,15 @@ module Mongo
412
456
  def resuming?
413
457
  !!@resuming
414
458
  end
459
+
460
+ # Recreates the current cursor (typically as a consequence of attempting
461
+ # to resume the change stream)
462
+ def recreate_cursor!(context = nil)
463
+ @timed_out = false
464
+
465
+ close
466
+ create_cursor!(context&.remaining_timeout_ms)
467
+ end
415
468
  end
416
469
  end
417
470
  end
@@ -15,6 +15,8 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+ require 'mongo/cursor_host'
19
+
18
20
  module Mongo
19
21
  class Collection
20
22
  class View
@@ -24,13 +26,7 @@ module Mongo
24
26
  #
25
27
  # @since 2.0.0
26
28
  module Iterable
27
-
28
- # Returns the cursor associated with this view, if any.
29
- #
30
- # @return [ nil | Cursor ] The cursor, if any.
31
- #
32
- # @api private
33
- attr_reader :cursor
29
+ include Mongo::CursorHost
34
30
 
35
31
  # Iterate through documents returned by a query with this +View+.
36
32
  #
@@ -45,48 +41,21 @@ module Mongo
45
41
  #
46
42
  # @yieldparam [ Hash ] Each matching document.
47
43
  def each
48
- # If the caching cursor is closed and was not fully iterated,
49
- # the documents we have in it are not the complete result set and
50
- # we have no way of completing that iteration.
51
- # Therefore, discard that cursor and start iteration again.
52
- # The case of the caching cursor not being closed and not having
53
- # been fully iterated isn't tested - see RUBY-2773.
54
- @cursor = if use_query_cache? && cached_cursor && (
55
- cached_cursor.fully_iterated? || !cached_cursor.closed?
56
- )
57
- cached_cursor
58
- else
59
- session = client.send(:get_session, @options)
60
- select_cursor(session).tap do |cursor|
61
- if use_query_cache?
62
- # No need to store the cursor in the query cache if there is
63
- # already a cached cursor stored at this key.
64
- QueryCache.set(cursor, **cache_options)
65
- end
66
- end
67
- end
44
+ @cursor = prefer_cached_cursor? ? cached_cursor : new_cursor_for_iteration
45
+ return @cursor.to_enum unless block_given?
68
46
 
69
- if use_query_cache?
70
- # If a query with a limit is performed, the query cache will
71
- # re-use results from an earlier query with the same or larger
72
- # limit, and then impose the lower limit during iteration.
73
- limit_for_cached_query = respond_to?(:limit) ? QueryCache.normalized_limit(limit) : nil
74
- end
47
+ limit_for_cached_query = compute_limit_for_cached_query
75
48
 
76
- if block_given?
77
- # Ruby versions 2.5 and older do not support arr[0..nil] syntax, so
78
- # this must be a separate conditional.
79
- cursor_to_iterate = if limit_for_cached_query
80
- @cursor.to_a[0...limit_for_cached_query]
81
- else
82
- @cursor
83
- end
84
-
85
- cursor_to_iterate.each do |doc|
86
- yield doc
87
- end
49
+ # Ruby versions 2.5 and older do not support arr[0..nil] syntax, so
50
+ # this must be a separate conditional.
51
+ cursor_to_iterate = if limit_for_cached_query
52
+ @cursor.to_a[0...limit_for_cached_query]
88
53
  else
89
- @cursor.to_enum
54
+ @cursor
55
+ end
56
+
57
+ cursor_to_iterate.each do |doc|
58
+ yield doc
90
59
  end
91
60
  end
92
61
 
@@ -100,7 +69,7 @@ module Mongo
100
69
  #
101
70
  # @return [ nil ] Always nil.
102
71
  #
103
- # @raise [ Error::OperationFailure ] If the server cursor close fails.
72
+ # @raise [ Error::OperationFailure::Family ] If the server cursor close fails.
104
73
  #
105
74
  # @since 2.1.0
106
75
  def close_query
@@ -113,18 +82,25 @@ module Mongo
113
82
  private
114
83
 
115
84
  def select_cursor(session)
85
+ context = Operation::Context.new(
86
+ client: client,
87
+ session: session,
88
+ operation_timeouts: operation_timeouts,
89
+ view: self
90
+ )
91
+
116
92
  if respond_to?(:write?, true) && write?
117
93
  server = server_selector.select_server(cluster, nil, session, write_aggregation: true)
118
- result = send_initial_query(server, session)
94
+ result = send_initial_query(server, context)
119
95
 
120
96
  if use_query_cache?
121
- CachingCursor.new(view, result, server, session: session)
97
+ CachingCursor.new(view, result, server, session: session, context: context)
122
98
  else
123
- Cursor.new(view, result, server, session: session)
99
+ Cursor.new(view, result, server, session: session, context: context)
124
100
  end
125
101
  else
126
- read_with_retry_cursor(session, server_selector, view) do |server|
127
- send_initial_query(server, session)
102
+ read_with_retry_cursor(session, server_selector, view, context: context) do |server|
103
+ send_initial_query(server, context)
128
104
  end
129
105
  end
130
106
  end
@@ -162,29 +138,27 @@ module Mongo
162
138
  let: options[:let],
163
139
  limit: limit,
164
140
  allow_disk_use: options[:allow_disk_use],
141
+ allow_partial_results: options[:allow_partial_results],
165
142
  read: read,
166
143
  read_concern: options[:read_concern] || read_concern,
167
144
  batch_size: batch_size,
168
145
  hint: options[:hint],
169
146
  max_scan: options[:max_scan],
170
- max_time_ms: options[:max_time_ms],
171
147
  max_value: options[:max_value],
172
148
  min_value: options[:min_value],
173
149
  no_cursor_timeout: options[:no_cursor_timeout],
174
150
  return_key: options[:return_key],
175
151
  show_disk_loc: options[:show_disk_loc],
176
152
  comment: options[:comment],
177
- oplog_replay: if (v = options[:oplog_replay]).nil?
178
- collection.options[:oplog_replay]
179
- else
180
- v
181
- end,
153
+ oplog_replay: oplog_replay
182
154
  }
183
155
 
184
156
  if spec[:oplog_replay]
185
157
  collection.client.log_warn("The :oplog_replay option is deprecated and ignored by MongoDB 4.4 and later")
186
158
  end
187
159
 
160
+ maybe_set_tailable_options(spec)
161
+
188
162
  if explained?
189
163
  spec[:explain] = options[:explain]
190
164
  Operation::Explain.new(spec)
@@ -193,13 +167,71 @@ module Mongo
193
167
  end
194
168
  end
195
169
 
196
- def send_initial_query(server, session = nil)
197
- initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
170
+ def send_initial_query(server, context)
171
+ operation = initial_query_op(context.session)
172
+ if server.load_balancer?
173
+ # Connection will be checked in when cursor is drained.
174
+ connection = server.pool.check_out(context: context)
175
+ operation.execute_with_connection(connection, context: context)
176
+ else
177
+ operation.execute(server, context: context)
178
+ end
198
179
  end
199
180
 
200
181
  def use_query_cache?
201
182
  QueryCache.enabled? && !collection.system_collection?
202
183
  end
184
+
185
+ # If the caching cursor is closed and was not fully iterated,
186
+ # the documents we have in it are not the complete result set and
187
+ # we have no way of completing that iteration.
188
+ # Therefore, discard that cursor and start iteration again.
189
+ def prefer_cached_cursor?
190
+ use_query_cache? &&
191
+ cached_cursor &&
192
+ (cached_cursor.fully_iterated? || !cached_cursor.closed?)
193
+ end
194
+
195
+ # Start a new cursor for use when iterating (via #each).
196
+ def new_cursor_for_iteration
197
+ session = client.get_session(@options)
198
+ select_cursor(session).tap do |cursor|
199
+ if use_query_cache?
200
+ # No need to store the cursor in the query cache if there is
201
+ # already a cached cursor stored at this key.
202
+ QueryCache.set(cursor, **cache_options)
203
+ end
204
+ end
205
+ end
206
+
207
+ def compute_limit_for_cached_query
208
+ return nil unless use_query_cache? && respond_to?(:limit)
209
+
210
+ # If a query with a limit is performed, the query cache will
211
+ # re-use results from an earlier query with the same or larger
212
+ # limit, and then impose the lower limit during iteration.
213
+ return QueryCache.normalized_limit(limit)
214
+ end
215
+
216
+ # Add tailable cusror options to the command specifiction if needed.
217
+ #
218
+ # @param [ Hash ] spec The command specification.
219
+ def maybe_set_tailable_options(spec)
220
+ case cursor_type
221
+ when :tailable
222
+ spec[:tailable] = true
223
+ when :tailable_await
224
+ spec[:tailable] = true
225
+ spec[:await_data] = true
226
+ end
227
+ end
228
+
229
+ # @return [ true | false | nil ] options[:oplog_replay], if
230
+ # set, otherwise the same option from the collection.
231
+ def oplog_replay
232
+ v = options[:oplog_replay]
233
+ v.nil? ? collection.options[:oplog_replay] : v
234
+ end
203
235
  end
204
236
  end
205
237
  end