mongo 2.20.2 → 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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/Rakefile +11 -11
  4. data/lib/mongo/address.rb +22 -3
  5. data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
  6. data/lib/mongo/auth/base.rb +1 -1
  7. data/lib/mongo/bulk_write.rb +35 -2
  8. data/lib/mongo/client.rb +38 -6
  9. data/lib/mongo/client_encryption.rb +6 -3
  10. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
  11. data/lib/mongo/cluster/sdam_flow.rb +20 -7
  12. data/lib/mongo/cluster.rb +14 -4
  13. data/lib/mongo/collection/helpers.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
  15. data/lib/mongo/collection/view/aggregation.rb +33 -99
  16. data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
  17. data/lib/mongo/collection/view/change_stream.rb +80 -27
  18. data/lib/mongo/collection/view/iterable.rb +76 -60
  19. data/lib/mongo/collection/view/map_reduce.rb +25 -8
  20. data/lib/mongo/collection/view/readable.rb +79 -30
  21. data/lib/mongo/collection/view/writable.rb +109 -48
  22. data/lib/mongo/collection/view.rb +43 -3
  23. data/lib/mongo/collection.rb +158 -23
  24. data/lib/mongo/crypt/auto_encrypter.rb +4 -6
  25. data/lib/mongo/crypt/binding.rb +4 -4
  26. data/lib/mongo/crypt/context.rb +20 -14
  27. data/lib/mongo/crypt/encryption_io.rb +56 -26
  28. data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
  29. data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
  30. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
  31. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
  32. data/lib/mongo/csot_timeout_holder.rb +119 -0
  33. data/lib/mongo/cursor/kill_spec.rb +5 -2
  34. data/lib/mongo/cursor/nontailable.rb +27 -0
  35. data/lib/mongo/cursor.rb +86 -24
  36. data/lib/mongo/cursor_host.rb +82 -0
  37. data/lib/mongo/database/view.rb +81 -14
  38. data/lib/mongo/database.rb +88 -18
  39. data/lib/mongo/error/operation_failure.rb +209 -204
  40. data/lib/mongo/error/server_timeout_error.rb +12 -0
  41. data/lib/mongo/error/socket_timeout_error.rb +3 -1
  42. data/lib/mongo/error/timeout_error.rb +23 -0
  43. data/lib/mongo/error.rb +2 -0
  44. data/lib/mongo/grid/fs_bucket.rb +45 -12
  45. data/lib/mongo/grid/stream/read.rb +15 -1
  46. data/lib/mongo/grid/stream/write.rb +21 -4
  47. data/lib/mongo/index/view.rb +77 -16
  48. data/lib/mongo/operation/context.rb +40 -2
  49. data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
  50. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  51. data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
  52. data/lib/mongo/operation/find/op_msg.rb +45 -0
  53. data/lib/mongo/operation/get_more/op_msg.rb +33 -0
  54. data/lib/mongo/operation/insert/op_msg.rb +3 -2
  55. data/lib/mongo/operation/insert/result.rb +4 -2
  56. data/lib/mongo/operation/list_collections/result.rb +1 -1
  57. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  58. data/lib/mongo/operation/op_msg_base.rb +3 -1
  59. data/lib/mongo/operation/result.rb +26 -5
  60. data/lib/mongo/operation/shared/executable.rb +12 -1
  61. data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
  62. data/lib/mongo/operation/shared/response_handling.rb +3 -3
  63. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  64. data/lib/mongo/operation/shared/timed.rb +52 -0
  65. data/lib/mongo/operation/shared/write.rb +4 -1
  66. data/lib/mongo/operation/update/op_msg.rb +2 -1
  67. data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
  68. data/lib/mongo/operation.rb +1 -0
  69. data/lib/mongo/protocol/message.rb +1 -4
  70. data/lib/mongo/protocol/msg.rb +2 -2
  71. data/lib/mongo/retryable/read_worker.rb +69 -29
  72. data/lib/mongo/retryable/write_worker.rb +49 -18
  73. data/lib/mongo/retryable.rb +8 -2
  74. data/lib/mongo/server/connection.rb +11 -5
  75. data/lib/mongo/server/connection_base.rb +22 -2
  76. data/lib/mongo/server/connection_pool.rb +32 -14
  77. data/lib/mongo/server/description/features.rb +1 -1
  78. data/lib/mongo/server/description.rb +18 -5
  79. data/lib/mongo/server/monitor.rb +7 -4
  80. data/lib/mongo/server/pending_connection.rb +7 -3
  81. data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
  82. data/lib/mongo/server.rb +11 -6
  83. data/lib/mongo/server_selector/base.rb +25 -9
  84. data/lib/mongo/session.rb +78 -9
  85. data/lib/mongo/socket/ssl.rb +113 -30
  86. data/lib/mongo/socket/tcp.rb +40 -6
  87. data/lib/mongo/socket.rb +154 -25
  88. data/lib/mongo/uri/options_mapper.rb +1 -0
  89. data/lib/mongo/version.rb +15 -4
  90. data/lib/mongo.rb +1 -0
  91. data/spec/atlas/atlas_connectivity_spec.rb +4 -0
  92. data/spec/atlas/operations_spec.rb +4 -0
  93. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
  94. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
  95. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
  96. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
  97. data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
  98. data/spec/integration/connection_pool_populator_spec.rb +2 -0
  99. data/spec/integration/cursor_pinning_spec.rb +15 -60
  100. data/spec/integration/cursor_reaping_spec.rb +1 -1
  101. data/spec/integration/docs_examples_spec.rb +1 -1
  102. data/spec/integration/ocsp_verifier_spec.rb +99 -30
  103. data/spec/integration/operation_failure_code_spec.rb +1 -1
  104. data/spec/integration/operation_failure_message_spec.rb +3 -3
  105. data/spec/integration/reconnect_spec.rb +2 -8
  106. data/spec/integration/retryable_errors_spec.rb +2 -2
  107. data/spec/integration/sdam_error_handling_spec.rb +2 -1
  108. data/spec/integration/search_indexes_prose_spec.rb +4 -0
  109. data/spec/integration/server_spec.rb +4 -3
  110. data/spec/integration/srv_monitoring_spec.rb +3 -2
  111. data/spec/integration/srv_spec.rb +4 -0
  112. data/spec/integration/transactions_api_examples_spec.rb +2 -0
  113. data/spec/kerberos/kerberos_spec.rb +4 -0
  114. data/spec/lite_spec_helper.rb +3 -1
  115. data/spec/mongo/auth/user/view_spec.rb +1 -1
  116. data/spec/mongo/caching_cursor_spec.rb +1 -1
  117. data/spec/mongo/client_encryption_spec.rb +1 -0
  118. data/spec/mongo/client_spec.rb +158 -4
  119. data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
  120. data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
  121. data/spec/mongo/collection_spec.rb +5 -6
  122. data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
  123. data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
  124. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
  125. data/spec/mongo/crypt/handle_spec.rb +1 -1
  126. data/spec/mongo/cursor_spec.rb +26 -9
  127. data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
  128. data/spec/mongo/operation/context_spec.rb +79 -0
  129. data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
  130. data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
  131. data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
  132. data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
  133. data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
  134. data/spec/mongo/operation/shared/csot/examples.rb +113 -0
  135. data/spec/mongo/query_cache_spec.rb +243 -225
  136. data/spec/mongo/retryable_spec.rb +1 -0
  137. data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
  138. data/spec/mongo/socket/ssl_spec.rb +0 -10
  139. data/spec/runners/change_streams/test.rb +2 -2
  140. data/spec/runners/crud/operation.rb +1 -1
  141. data/spec/runners/crud/verifier.rb +3 -1
  142. data/spec/runners/transactions/operation.rb +4 -6
  143. data/spec/runners/unified/ambiguous_operations.rb +13 -0
  144. data/spec/runners/unified/assertions.rb +4 -0
  145. data/spec/runners/unified/change_stream_operations.rb +14 -24
  146. data/spec/runners/unified/crud_operations.rb +82 -59
  147. data/spec/runners/unified/ddl_operations.rb +38 -7
  148. data/spec/runners/unified/grid_fs_operations.rb +37 -2
  149. data/spec/runners/unified/support_operations.rb +43 -4
  150. data/spec/runners/unified/test.rb +22 -10
  151. data/spec/runners/unified.rb +1 -1
  152. data/spec/solo/clean_exit_spec.rb +2 -0
  153. data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
  154. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
  155. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
  156. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
  157. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  158. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
  159. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
  160. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
  161. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
  162. data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
  163. data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
  164. data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
  165. data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
  166. data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
  167. data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
  168. data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
  169. data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
  170. data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
  171. data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
  172. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
  173. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
  174. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
  175. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
  176. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
  177. data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
  178. data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
  179. data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
  180. data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
  181. data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
  182. data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
  183. data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
  184. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
  185. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
  186. data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
  187. data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
  188. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
  189. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
  190. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
  191. data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
  192. data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
  193. data/spec/support/certificates/atlas-ocsp.crt +107 -107
  194. data/spec/support/cluster_tools.rb +3 -3
  195. data/spec/support/common_shortcuts.rb +39 -21
  196. data/spec/support/constraints.rb +0 -10
  197. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
  198. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
  199. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
  200. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
  201. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
  202. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
  203. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
  204. data/spec/support/dns.rb +16 -0
  205. data/spec/support/shared/session.rb +2 -2
  206. data/spec/support/spec_setup.rb +2 -2
  207. data/spec/support/utils.rb +3 -1
  208. metadata +91 -153
  209. data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
  210. data/spec/shared/CANDIDATE.md +0 -28
  211. data/spec/shared/LICENSE +0 -20
  212. data/spec/shared/bin/get-mongodb-download-url +0 -17
  213. data/spec/shared/bin/s3-copy +0 -45
  214. data/spec/shared/bin/s3-upload +0 -69
  215. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  216. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  217. data/spec/shared/lib/mrss/constraints.rb +0 -378
  218. data/spec/shared/lib/mrss/docker_runner.rb +0 -298
  219. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  220. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  221. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  222. data/spec/shared/lib/mrss/release/candidate.rb +0 -281
  223. data/spec/shared/lib/mrss/release/product_data.rb +0 -144
  224. data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
  225. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  226. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  227. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  228. data/spec/shared/lib/mrss/utils.rb +0 -37
  229. data/spec/shared/lib/tasks/candidate.rake +0 -64
  230. data/spec/shared/share/Dockerfile.erb +0 -251
  231. data/spec/shared/share/haproxy-1.conf +0 -16
  232. data/spec/shared/share/haproxy-2.conf +0 -17
  233. data/spec/shared/shlib/config.sh +0 -27
  234. data/spec/shared/shlib/distro.sh +0 -84
  235. data/spec/shared/shlib/server.sh +0 -423
  236. data/spec/shared/shlib/set_env.sh +0 -110
  237. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
  238. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
  239. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
  240. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
  241. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
  242. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
  243. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
  244. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
  245. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
  246. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
  247. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
  248. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
  249. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
  250. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
  251. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
  252. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
  253. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
  254. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
  255. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
  256. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
  257. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
  258. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
  259. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
  260. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
  261. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
  262. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
  263. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
  264. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
  265. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
  266. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
  267. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
  268. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
  269. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
  270. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
  271. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
  272. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
  273. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
  274. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
  275. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
  276. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
  277. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
  278. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
  279. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
@@ -8,6 +8,10 @@ describe Mongo::Cursor do
8
8
  authorized_client['cursor_spec_collection']
9
9
  end
10
10
 
11
+ let(:context) do
12
+ Mongo::Operation::Context.new(client: authorized_client)
13
+ end
14
+
11
15
  before do
12
16
  authorized_collection.drop
13
17
  end
@@ -18,7 +22,7 @@ describe Mongo::Cursor do
18
22
  end
19
23
 
20
24
  let(:reply) do
21
- view.send(:send_initial_query, server)
25
+ view.send(:send_initial_query, server, context)
22
26
  end
23
27
 
24
28
  let(:cursor) do
@@ -118,7 +122,7 @@ describe Mongo::Cursor do
118
122
  end
119
123
 
120
124
  let(:reply) do
121
- view.send(:send_initial_query, server)
125
+ view.send(:send_initial_query, server, context)
122
126
  end
123
127
 
124
128
  let(:cursor) do
@@ -170,7 +174,11 @@ describe Mongo::Cursor do
170
174
 
171
175
  before do
172
176
  expect(cursor).to receive(:get_more_operation).and_return(op).ordered
173
- expect(op).to receive(:execute).and_raise(Mongo::Error::SocketError).ordered
177
+ if SpecConfig.instance.connect_options[:connect] == :load_balanced
178
+ expect(op).to receive(:execute_with_connection).and_raise(Mongo::Error::SocketError).ordered
179
+ else
180
+ expect(op).to receive(:execute).and_raise(Mongo::Error::SocketError).ordered
181
+ end
174
182
  end
175
183
 
176
184
  it 'raises the error' do
@@ -617,6 +625,9 @@ describe Mongo::Cursor do
617
625
  allow(reply).to receive(:connection_description).and_return(conn_desc)
618
626
  allow(reply).to receive(:cursor_id).and_return(42)
619
627
  allow(reply).to receive(:connection_global_id).and_return(1)
628
+ if SpecConfig.instance.connect_options[:connect] == :load_balanced
629
+ allow(reply).to receive(:connection).and_return(nil)
630
+ end
620
631
  end
621
632
  end
622
633
 
@@ -645,7 +656,7 @@ describe Mongo::Cursor do
645
656
  end
646
657
 
647
658
  let(:reply) do
648
- view.send(:send_initial_query, authorized_primary)
659
+ view.send(:send_initial_query, authorized_primary, context)
649
660
  end
650
661
 
651
662
  let(:cursor) do
@@ -721,7 +732,7 @@ describe Mongo::Cursor do
721
732
  end
722
733
 
723
734
  let(:reply) do
724
- view.send(:send_initial_query, server)
735
+ view.send(:send_initial_query, server, context)
725
736
  end
726
737
 
727
738
  let(:cursor) do
@@ -770,10 +781,16 @@ describe Mongo::Cursor do
770
781
 
771
782
  it 'does not raise an error' do
772
783
  cursor
773
- server.with_connection do |conn|
774
- expect(conn).to receive(:deliver)
775
- .at_least(:once)
776
- .and_raise(Mongo::Error::SocketError, "test error")
784
+ if SpecConfig.instance.connect_options[:connect] == :load_balanced
785
+ expect(cursor.connection).to receive(:deliver)
786
+ .at_least(:once)
787
+ .and_raise(Mongo::Error::SocketError, "test error")
788
+ else
789
+ server.with_connection do |conn|
790
+ expect(conn).to receive(:deliver)
791
+ .at_least(:once)
792
+ .and_raise(Mongo::Error::SocketError, "test error")
793
+ end
777
794
  end
778
795
  expect do
779
796
  cursor.close
@@ -39,7 +39,7 @@ describe Mongo::Error::OperationFailure do
39
39
 
40
40
  begin
41
41
  authorized_client['foo'].insert_one(test: 1)
42
- rescue Mongo::Error::OperationFailure => exc
42
+ rescue Mongo::Error::OperationFailure::Family => exc
43
43
  expect(exc.details).to eq(exc.document['writeConcernError']['errInfo'])
44
44
  expect(exc.server_message).to eq(exc.document['writeConcernError']['errmsg'])
45
45
  expect(exc.code).to eq(exc.document['writeConcernError']['code'])
@@ -90,7 +90,7 @@ describe Mongo::Error::OperationFailure do
90
90
  it 'succeeds and prints the error' do
91
91
  begin
92
92
  collection.insert_one({x: 1})
93
- rescue Mongo::Error::OperationFailure => e
93
+ rescue Mongo::Error::OperationFailure::Family => e
94
94
  insert_events = subscriber.succeeded_events.select { |e| e.command_name == "insert" }
95
95
  expect(insert_events.length).to eq 1
96
96
  expect(e.message).to match(/\[#{e.code}(:.*)?\].+ -- .+/)
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lite_spec_helper'
4
+
5
+ describe Mongo::Operation::Context do
6
+ describe '#initialize' do
7
+ context 'when timeout_ms is negative' do
8
+ it 'raises an error' do
9
+ expect do
10
+ described_class.new(operation_timeouts: { operation_timeout_ms: -1 })
11
+ end.to raise_error ArgumentError, /must be a non-negative integer/
12
+ end
13
+ end
14
+ end
15
+
16
+ describe '#deadline' do
17
+ let(:context) { described_class.new(operation_timeouts: { operation_timeout_ms: timeout_ms }) }
18
+
19
+ context 'when timeout_ms is nil' do
20
+ let(:timeout_ms) { nil }
21
+
22
+ it 'returns nil' do
23
+ expect(context.deadline).to be_nil
24
+ end
25
+ end
26
+
27
+ context 'when timeout_ms is zero' do
28
+ let(:timeout_ms) { 0 }
29
+
30
+ it 'returns nil' do
31
+ expect(context.deadline).to eq(0)
32
+ end
33
+ end
34
+
35
+ context 'when timeout_ms is positive' do
36
+ before do
37
+ allow(Mongo::Utils).to receive(:monotonic_time).and_return(100.0)
38
+ end
39
+
40
+ let(:timeout_ms) { 10_000 }
41
+
42
+ it 'calculates the deadline' do
43
+ expect(context.deadline).to eq(110)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#remaining_timeout_ms' do
49
+ let(:context) { described_class.new(operation_timeouts: { operation_timeout_ms: timeout_ms }) }
50
+
51
+ context 'when timeout_ms is nil' do
52
+ let(:timeout_ms) { nil }
53
+
54
+ it 'returns nil' do
55
+ expect(context.remaining_timeout_ms).to be_nil
56
+ end
57
+ end
58
+
59
+ context 'when timeout_ms is zero' do
60
+ let(:timeout_ms) { 0 }
61
+
62
+ it 'returns nil' do
63
+ expect(context.remaining_timeout_ms).to be_nil
64
+ end
65
+ end
66
+
67
+ context 'when timeout_ms is positive' do
68
+ before do
69
+ allow(Mongo::Utils).to receive(:monotonic_time).and_return(100.0, 105.0)
70
+ end
71
+
72
+ let(:timeout_ms) { 10_000 }
73
+
74
+ it 'calculates the remaining time' do
75
+ expect(context.remaining_timeout_ms).to eq(5_000)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -2,8 +2,12 @@
2
2
  # rubocop:todo all
3
3
 
4
4
  require 'spec_helper'
5
+ require_relative '../shared/csot/examples'
5
6
 
6
7
  describe Mongo::Operation::Create::OpMsg do
8
+ include CSOT::Examples
9
+
10
+ let(:context) { Mongo::Operation::Context.new }
7
11
 
8
12
  let(:write_concern) do
9
13
  Mongo::WriteConcern.get(w: :majority)
@@ -73,8 +77,6 @@ describe Mongo::Operation::Create::OpMsg do
73
77
  end
74
78
 
75
79
  describe '#selector' do
76
- min_server_fcv '3.6'
77
-
78
80
  it 'does not mutate user input' do
79
81
  user_input = IceNine.deep_freeze(spec.dup)
80
82
  expect do
@@ -87,158 +89,152 @@ describe Mongo::Operation::Create::OpMsg do
87
89
  # https://jira.mongodb.org/browse/RUBY-2224
88
90
  require_no_linting
89
91
 
90
- context 'when the server supports OP_MSG' do
92
+ let(:global_args) do
93
+ {
94
+ create: TEST_COLL,
95
+ writeConcern: write_concern.options,
96
+ '$db' => SpecConfig.instance.test_db,
97
+ lsid: session.session_id
98
+ }
99
+ end
100
+
101
+ let(:session) do
102
+ authorized_client.start_session
103
+ end
91
104
 
92
- let(:global_args) do
93
- {
94
- create: TEST_COLL,
95
- writeConcern: write_concern.options,
96
- '$db' => SpecConfig.instance.test_db,
97
- lsid: session.session_id
98
- }
105
+ context 'when the topology is replica set or sharded' do
106
+ require_topology :replica_set, :sharded
107
+
108
+ let(:expected_global_args) do
109
+ global_args.merge(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
99
110
  end
100
111
 
101
- let(:session) do
102
- authorized_client.start_session
112
+ it 'creates the correct OP_MSG message' do
113
+ authorized_client.command(ping:1)
114
+ expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args)
115
+ op.send(:message, connection)
103
116
  end
117
+ end
104
118
 
105
- context 'when the topology is replica set or sharded' do
106
- min_server_fcv '3.6'
107
- require_topology :replica_set, :sharded
119
+ context 'when the topology is standalone' do
120
+ require_topology :single
108
121
 
109
- let(:expected_global_args) do
110
- global_args.merge(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
111
- end
122
+ let(:expected_global_args) do
123
+ global_args
124
+ end
112
125
 
113
- it 'creates the correct OP_MSG message' do
114
- authorized_client.command(ping:1)
115
- expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args)
116
- op.send(:message, connection)
117
- end
126
+ it 'creates the correct OP_MSG message' do
127
+ authorized_client.command(ping:1)
128
+ expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args)
129
+ op.send(:message, connection)
118
130
  end
119
131
 
120
- context 'when the topology is standalone' do
121
- min_server_fcv '3.6'
122
- require_topology :single
132
+ context 'when an implicit session is created and the topology is then updated and the server does not support sessions' do
133
+ # Mocks on features are incompatible with linting
134
+ require_no_linting
123
135
 
124
136
  let(:expected_global_args) do
125
- global_args
126
- end
127
-
128
- it 'creates the correct OP_MSG message' do
129
- authorized_client.command(ping:1)
130
- expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args)
131
- op.send(:message, connection)
132
- end
133
-
134
- context 'when an implicit session is created and the topology is then updated and the server does not support sessions' do
135
- # Mocks on features are incompatible with linting
136
- require_no_linting
137
-
138
- let(:expected_global_args) do
139
- global_args.dup.tap do |args|
140
- args.delete(:lsid)
141
- end
137
+ global_args.dup.tap do |args|
138
+ args.delete(:lsid)
142
139
  end
140
+ end
143
141
 
144
- let(:session) do
145
- Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
146
- allow(session).to receive(:session_id).and_return(42)
147
- session.should be_implicit
148
- end
142
+ let(:session) do
143
+ Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
144
+ allow(session).to receive(:session_id).and_return(42)
145
+ session.should be_implicit
149
146
  end
147
+ end
150
148
 
151
- it 'creates the correct OP_MSG message' do
152
- RSpec::Mocks.with_temporary_scope do
153
- expect(connection.features).to receive(:sessions_enabled?).and_return(false)
149
+ it 'creates the correct OP_MSG message' do
150
+ RSpec::Mocks.with_temporary_scope do
151
+ expect(connection.features).to receive(:sessions_enabled?).and_return(false)
154
152
 
155
- expect(expected_global_args[:session]).to be nil
156
- expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args)
157
- op.send(:message, connection)
158
- end
153
+ expect(expected_global_args[:session]).to be nil
154
+ expect(Mongo::Protocol::Msg).to receive(:new).with([], {}, expected_global_args)
155
+ op.send(:message, connection)
159
156
  end
160
157
  end
161
158
  end
159
+ end
162
160
 
163
- context 'when the write concern is 0' do
161
+ context 'when the write concern is 0' do
164
162
 
165
- let(:write_concern) do
166
- Mongo::WriteConcern.get(w: 0)
167
- end
163
+ let(:write_concern) do
164
+ Mongo::WriteConcern.get(w: 0)
165
+ end
168
166
 
169
- context 'when the session is implicit' do
167
+ context 'when the session is implicit' do
170
168
 
171
- let(:session) do
172
- Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
173
- allow(session).to receive(:session_id).and_return(42)
174
- session.should be_implicit
175
- end
169
+ let(:session) do
170
+ Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
171
+ allow(session).to receive(:session_id).and_return(42)
172
+ session.should be_implicit
176
173
  end
174
+ end
177
175
 
178
- context 'when the topology is replica set or sharded' do
179
- min_server_fcv '3.6'
180
- require_topology :replica_set, :sharded
176
+ context 'when the topology is replica set or sharded' do
177
+ require_topology :replica_set, :sharded
181
178
 
182
- let(:expected_global_args) do
183
- global_args.dup.tap do |args|
184
- args.delete(:lsid)
185
- args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
186
- end
179
+ let(:expected_global_args) do
180
+ global_args.dup.tap do |args|
181
+ args.delete(:lsid)
182
+ args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
187
183
  end
184
+ end
188
185
 
189
- it 'does not send a session id in the command' do
190
- authorized_client.command(ping:1)
191
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args)
192
- op.send(:message, connection)
193
- end
186
+ it 'does not send a session id in the command' do
187
+ authorized_client.command(ping:1)
188
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args)
189
+ op.send(:message, connection)
194
190
  end
191
+ end
195
192
 
196
- context 'when the topology is standalone' do
197
- min_server_fcv '3.6'
198
- require_topology :single
193
+ context 'when the topology is standalone' do
194
+ require_topology :single
199
195
 
200
- let(:expected_global_args) do
201
- global_args.dup.tap do |args|
202
- args.delete(:lsid)
203
- end
196
+ let(:expected_global_args) do
197
+ global_args.dup.tap do |args|
198
+ args.delete(:lsid)
204
199
  end
200
+ end
205
201
 
206
- it 'creates the correct OP_MSG message' do
207
- authorized_client.command(ping:1)
208
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args)
209
- op.send(:message, connection)
210
- end
202
+ it 'creates the correct OP_MSG message' do
203
+ authorized_client.command(ping:1)
204
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args)
205
+ op.send(:message, connection)
211
206
  end
212
207
  end
208
+ end
213
209
 
214
- context 'when the session is explicit' do
215
- min_server_fcv '3.6'
216
- require_topology :replica_set, :sharded
210
+ context 'when the session is explicit' do
211
+ require_topology :replica_set, :sharded
217
212
 
218
- let(:session) do
219
- authorized_client.start_session
220
- end
213
+ let(:session) do
214
+ authorized_client.start_session
215
+ end
221
216
 
222
- before do
223
- session.should_not be_implicit
224
- end
217
+ before do
218
+ session.should_not be_implicit
219
+ end
225
220
 
226
- let(:expected_global_args) do
227
- global_args.dup.tap do |args|
228
- args.delete(:lsid)
229
- args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
230
- end
221
+ let(:expected_global_args) do
222
+ global_args.dup.tap do |args|
223
+ args.delete(:lsid)
224
+ args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
231
225
  end
226
+ end
232
227
 
233
- it 'does not send a session id in the command' do
234
- authorized_client.command(ping:1)
235
- RSpec::Mocks.with_temporary_scope do
236
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args)
237
- op.send(:message, connection)
238
- end
228
+ it 'does not send a session id in the command' do
229
+ authorized_client.command(ping:1)
230
+ RSpec::Mocks.with_temporary_scope do
231
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come], {}, expected_global_args)
232
+ op.send(:message, connection)
239
233
  end
240
234
  end
241
235
  end
242
236
  end
243
237
  end
238
+
239
+ it_behaves_like 'a CSOT-compliant OpMsg subclass'
244
240
  end
@@ -2,8 +2,12 @@
2
2
  # rubocop:todo all
3
3
 
4
4
  require 'spec_helper'
5
+ require_relative '../shared/csot/examples'
5
6
 
6
7
  describe Mongo::Operation::Delete::OpMsg do
8
+ include CSOT::Examples
9
+
10
+ let(:context) { Mongo::Operation::Context.new }
7
11
 
8
12
  let(:write_concern) do
9
13
  Mongo::WriteConcern.get(w: :majority)
@@ -125,7 +129,6 @@ describe Mongo::Operation::Delete::OpMsg do
125
129
  end
126
130
 
127
131
  context 'when the topology is replica set or sharded' do
128
- min_server_fcv '3.6'
129
132
  require_topology :replica_set, :sharded
130
133
 
131
134
  let(:expected_global_args) do
@@ -140,7 +143,6 @@ describe Mongo::Operation::Delete::OpMsg do
140
143
  end
141
144
 
142
145
  context 'when the topology is standalone' do
143
- min_server_fcv '3.6'
144
146
  require_topology :single
145
147
 
146
148
  let(:expected_global_args) do
@@ -198,7 +200,6 @@ describe Mongo::Operation::Delete::OpMsg do
198
200
  end
199
201
 
200
202
  context 'when the topology is replica set or sharded' do
201
- min_server_fcv '3.6'
202
203
  require_topology :replica_set, :sharded
203
204
 
204
205
  let(:expected_global_args) do
@@ -216,7 +217,6 @@ describe Mongo::Operation::Delete::OpMsg do
216
217
  end
217
218
 
218
219
  context 'when the topology is standalone' do
219
- min_server_fcv '3.6'
220
220
  require_topology :single
221
221
 
222
222
  let(:expected_global_args) do
@@ -234,7 +234,6 @@ describe Mongo::Operation::Delete::OpMsg do
234
234
  end
235
235
 
236
236
  context 'when the session is explicit' do
237
- min_server_fcv '3.6'
238
237
  require_topology :replica_set, :sharded
239
238
 
240
239
  let(:session) do
@@ -263,4 +262,6 @@ describe Mongo::Operation::Delete::OpMsg do
263
262
  end
264
263
  end
265
264
  end
265
+
266
+ it_behaves_like 'a CSOT-compliant OpMsg subclass'
266
267
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require_relative '../shared/csot/examples'
5
+
6
+ describe Mongo::Operation::Find::OpMsg do
7
+ include CSOT::Examples
8
+
9
+ let(:spec) do
10
+ { coll_name: 'coll_name',
11
+ filter: {},
12
+ db_name: 'db_name' }
13
+ end
14
+
15
+ let(:op) { described_class.new(spec) }
16
+
17
+ context 'when it is a CSOT-compliant OpMsg' do
18
+ include_examples 'mock CSOT environment'
19
+
20
+ context 'when no timeout_ms set' do
21
+ it 'does not set maxTimeMS' do
22
+ expect(body.key?(:maxTimeMS)).to be false
23
+ end
24
+ end
25
+
26
+ context 'when timeout_ms is set' do
27
+ let(:remaining_timeout_sec) { 3 }
28
+
29
+ context 'when cursor is non-tailable' do
30
+ let(:cursor_type) { nil }
31
+
32
+ context 'when timeout_mode is cursor_lifetime' do
33
+ let(:timeout_mode) { :cursor_lifetime }
34
+
35
+ it 'sets maxTimeMS' do
36
+ expect(body[:maxTimeMS]).to be == 3_000
37
+ end
38
+ end
39
+
40
+ context 'when timeout_mode is iteration' do
41
+ let(:timeout_mode) { :iteration }
42
+
43
+ it 'omits maxTimeMS' do
44
+ expect(body[:maxTimeMS]).to be_nil
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'when cursor is tailable' do
50
+ let(:cursor_type) { :tailable }
51
+
52
+ it 'omits maxTimeMS' do
53
+ expect(body[:maxTimeMS]).to be_nil
54
+ end
55
+ end
56
+
57
+ context 'when cursor is tailable_await' do
58
+ let(:cursor_type) { :tailable_await }
59
+
60
+ it 'sets maxTimeMS' do
61
+ expect(body[:maxTimeMS]).to be == 3_000
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require_relative '../shared/csot/examples'
5
+
6
+ describe Mongo::Operation::GetMore::OpMsg do
7
+ include CSOT::Examples
8
+
9
+ let(:spec) do
10
+ {
11
+ options: {},
12
+ db_name: 'db_name',
13
+ coll_name: 'coll_name',
14
+ cursor_id: 1_234_567_890,
15
+ }
16
+ end
17
+
18
+ let(:op) { described_class.new(spec) }
19
+
20
+ context 'when it is a CSOT-compliant OpMsg' do
21
+ include_examples 'mock CSOT environment'
22
+
23
+ context 'when no timeout_ms set' do
24
+ it 'does not set maxTimeMS' do
25
+ expect(body.key?(:maxTimeMS)).to be false
26
+ end
27
+ end
28
+
29
+ context 'when timeout_ms is set' do
30
+ let(:remaining_timeout_sec) { 3 }
31
+
32
+ context 'when cursor is non-tailable' do
33
+ it 'omits maxTimeMS' do
34
+ expect(body[:maxTimeMS]).to be_nil
35
+ end
36
+ end
37
+
38
+ context 'when cursor is tailable' do
39
+ let(:cursor_type) { :tailable }
40
+
41
+ it 'omits maxTimeMS' do
42
+ expect(body[:maxTimeMS]).to be_nil
43
+ end
44
+ end
45
+
46
+ context 'when cursor is tailable_await' do
47
+ let(:cursor_type) { :tailable_await }
48
+
49
+ context 'when max_await_time_ms is omitted' do
50
+ it 'omits maxTimeMS' do
51
+ expect(body[:maxTimeMS]).to be_nil
52
+ end
53
+ end
54
+
55
+ context 'when max_await_time_ms is given' do
56
+ let(:max_await_time_ms) { 1_234 }
57
+
58
+ it 'sets maxTimeMS' do
59
+ expect(body[:maxTimeMS]).to be == 1_234
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end