mongo 2.20.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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/Rakefile +2 -2
  4. data/lib/mongo/address.rb +22 -3
  5. data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
  6. data/lib/mongo/auth/base.rb +1 -1
  7. data/lib/mongo/bulk_write.rb +35 -2
  8. data/lib/mongo/client.rb +38 -6
  9. data/lib/mongo/client_encryption.rb +6 -3
  10. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
  11. data/lib/mongo/cluster/sdam_flow.rb +20 -7
  12. data/lib/mongo/cluster.rb +14 -4
  13. data/lib/mongo/collection/helpers.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
  15. data/lib/mongo/collection/view/aggregation.rb +33 -99
  16. data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
  17. data/lib/mongo/collection/view/change_stream.rb +80 -27
  18. data/lib/mongo/collection/view/iterable.rb +76 -60
  19. data/lib/mongo/collection/view/map_reduce.rb +25 -8
  20. data/lib/mongo/collection/view/readable.rb +79 -30
  21. data/lib/mongo/collection/view/writable.rb +109 -48
  22. data/lib/mongo/collection/view.rb +43 -3
  23. data/lib/mongo/collection.rb +158 -23
  24. data/lib/mongo/crypt/auto_encrypter.rb +4 -6
  25. data/lib/mongo/crypt/binding.rb +4 -4
  26. data/lib/mongo/crypt/context.rb +20 -14
  27. data/lib/mongo/crypt/encryption_io.rb +56 -26
  28. data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
  29. data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
  30. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
  31. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
  32. data/lib/mongo/csot_timeout_holder.rb +119 -0
  33. data/lib/mongo/cursor/kill_spec.rb +5 -2
  34. data/lib/mongo/cursor/nontailable.rb +27 -0
  35. data/lib/mongo/cursor.rb +86 -24
  36. data/lib/mongo/cursor_host.rb +82 -0
  37. data/lib/mongo/database/view.rb +81 -14
  38. data/lib/mongo/database.rb +88 -18
  39. data/lib/mongo/error/operation_failure.rb +209 -204
  40. data/lib/mongo/error/server_timeout_error.rb +12 -0
  41. data/lib/mongo/error/socket_timeout_error.rb +3 -1
  42. data/lib/mongo/error/timeout_error.rb +23 -0
  43. data/lib/mongo/error.rb +2 -0
  44. data/lib/mongo/grid/fs_bucket.rb +45 -12
  45. data/lib/mongo/grid/stream/read.rb +15 -1
  46. data/lib/mongo/grid/stream/write.rb +21 -4
  47. data/lib/mongo/index/view.rb +77 -16
  48. data/lib/mongo/operation/context.rb +40 -2
  49. data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
  50. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  51. data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
  52. data/lib/mongo/operation/find/op_msg.rb +45 -0
  53. data/lib/mongo/operation/get_more/op_msg.rb +33 -0
  54. data/lib/mongo/operation/insert/op_msg.rb +3 -2
  55. data/lib/mongo/operation/insert/result.rb +4 -2
  56. data/lib/mongo/operation/list_collections/result.rb +1 -1
  57. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  58. data/lib/mongo/operation/op_msg_base.rb +3 -1
  59. data/lib/mongo/operation/result.rb +26 -5
  60. data/lib/mongo/operation/shared/executable.rb +12 -1
  61. data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
  62. data/lib/mongo/operation/shared/response_handling.rb +3 -3
  63. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  64. data/lib/mongo/operation/shared/timed.rb +52 -0
  65. data/lib/mongo/operation/shared/write.rb +4 -1
  66. data/lib/mongo/operation/update/op_msg.rb +2 -1
  67. data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
  68. data/lib/mongo/operation.rb +1 -0
  69. data/lib/mongo/protocol/message.rb +1 -4
  70. data/lib/mongo/protocol/msg.rb +2 -2
  71. data/lib/mongo/retryable/read_worker.rb +69 -29
  72. data/lib/mongo/retryable/write_worker.rb +49 -18
  73. data/lib/mongo/retryable.rb +8 -2
  74. data/lib/mongo/server/connection.rb +11 -5
  75. data/lib/mongo/server/connection_base.rb +22 -2
  76. data/lib/mongo/server/connection_pool.rb +32 -14
  77. data/lib/mongo/server/description/features.rb +1 -1
  78. data/lib/mongo/server/description.rb +18 -5
  79. data/lib/mongo/server/monitor.rb +7 -4
  80. data/lib/mongo/server/pending_connection.rb +7 -3
  81. data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
  82. data/lib/mongo/server.rb +11 -6
  83. data/lib/mongo/server_selector/base.rb +25 -9
  84. data/lib/mongo/session.rb +78 -9
  85. data/lib/mongo/socket/ssl.rb +109 -17
  86. data/lib/mongo/socket/tcp.rb +40 -6
  87. data/lib/mongo/socket.rb +154 -25
  88. data/lib/mongo/uri/options_mapper.rb +1 -0
  89. data/lib/mongo/version.rb +1 -1
  90. data/lib/mongo.rb +1 -0
  91. data/spec/atlas/atlas_connectivity_spec.rb +4 -0
  92. data/spec/atlas/operations_spec.rb +4 -0
  93. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
  94. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
  95. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
  96. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
  97. data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
  98. data/spec/integration/connection_pool_populator_spec.rb +2 -0
  99. data/spec/integration/cursor_pinning_spec.rb +15 -60
  100. data/spec/integration/cursor_reaping_spec.rb +1 -1
  101. data/spec/integration/docs_examples_spec.rb +1 -1
  102. data/spec/integration/operation_failure_code_spec.rb +1 -1
  103. data/spec/integration/operation_failure_message_spec.rb +3 -3
  104. data/spec/integration/retryable_errors_spec.rb +2 -2
  105. data/spec/integration/sdam_error_handling_spec.rb +2 -1
  106. data/spec/integration/search_indexes_prose_spec.rb +4 -0
  107. data/spec/integration/server_spec.rb +4 -3
  108. data/spec/integration/transactions_api_examples_spec.rb +2 -0
  109. data/spec/kerberos/kerberos_spec.rb +4 -0
  110. data/spec/lite_spec_helper.rb +3 -1
  111. data/spec/mongo/auth/user/view_spec.rb +1 -1
  112. data/spec/mongo/caching_cursor_spec.rb +1 -1
  113. data/spec/mongo/client_encryption_spec.rb +1 -0
  114. data/spec/mongo/client_spec.rb +158 -4
  115. data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
  116. data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
  117. data/spec/mongo/collection_spec.rb +5 -6
  118. data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
  119. data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
  120. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
  121. data/spec/mongo/crypt/handle_spec.rb +1 -1
  122. data/spec/mongo/cursor_spec.rb +26 -9
  123. data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
  124. data/spec/mongo/operation/context_spec.rb +79 -0
  125. data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
  126. data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
  127. data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
  128. data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
  129. data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
  130. data/spec/mongo/operation/shared/csot/examples.rb +113 -0
  131. data/spec/mongo/query_cache_spec.rb +243 -225
  132. data/spec/mongo/retryable_spec.rb +1 -0
  133. data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
  134. data/spec/mongo/socket/ssl_spec.rb +0 -10
  135. data/spec/runners/change_streams/test.rb +2 -2
  136. data/spec/runners/crud/operation.rb +1 -1
  137. data/spec/runners/crud/verifier.rb +3 -1
  138. data/spec/runners/transactions/operation.rb +4 -6
  139. data/spec/runners/unified/ambiguous_operations.rb +13 -0
  140. data/spec/runners/unified/assertions.rb +4 -0
  141. data/spec/runners/unified/change_stream_operations.rb +14 -24
  142. data/spec/runners/unified/crud_operations.rb +82 -59
  143. data/spec/runners/unified/ddl_operations.rb +38 -7
  144. data/spec/runners/unified/grid_fs_operations.rb +37 -2
  145. data/spec/runners/unified/support_operations.rb +43 -4
  146. data/spec/runners/unified/test.rb +22 -10
  147. data/spec/runners/unified.rb +1 -1
  148. data/spec/solo/clean_exit_spec.rb +2 -0
  149. data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
  150. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
  151. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
  152. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
  153. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  154. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
  155. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
  156. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
  157. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
  158. data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
  159. data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
  160. data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
  161. data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
  162. data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
  163. data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
  164. data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
  165. data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
  166. data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
  167. data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
  168. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
  169. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
  170. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
  171. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
  172. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
  173. data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
  174. data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
  175. data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
  176. data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
  177. data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
  178. data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
  179. data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
  180. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
  181. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
  182. data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
  183. data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
  184. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
  185. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
  186. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
  187. data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
  188. data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
  189. data/spec/support/certificates/atlas-ocsp.crt +107 -107
  190. data/spec/support/cluster_tools.rb +3 -3
  191. data/spec/support/common_shortcuts.rb +2 -2
  192. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
  193. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
  194. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
  195. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
  196. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
  197. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
  198. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
  199. data/spec/support/shared/session.rb +2 -2
  200. data/spec/support/spec_setup.rb +2 -2
  201. data/spec/support/utils.rb +3 -1
  202. metadata +78 -91
  203. data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
  204. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
  205. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
  206. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
  207. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
  208. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
  209. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
  210. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
  211. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
  212. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
  213. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
  214. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
  215. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
  216. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
  217. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
  218. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
  219. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
  220. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
  221. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
  222. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
  223. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
  224. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
  225. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
  226. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
  227. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
  228. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
  229. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
  230. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
  231. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
  232. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
  233. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
  234. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
  235. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
  236. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
  237. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
  238. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
  239. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
  240. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
  241. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
  242. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
  243. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
  244. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
  245. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
  246. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
@@ -138,12 +138,19 @@ describe Mongo::QueryCache do
138
138
  end
139
139
 
140
140
  describe '#get' do
141
- let(:view) { double("Mongo::Collection::View") }
141
+ let(:view) do
142
+ double("Mongo::Collection::View").tap do |view|
143
+ allow(view).to receive(:client).and_return(client)
144
+ allow(view).to receive(:operation_timeouts).and_return({})
145
+ end
146
+ end
147
+
142
148
  let(:result) do
143
149
  double("Mongo::Operation::Result").tap do |result|
144
150
  allow(result).to receive(:is_a?).with(Mongo::Operation::Result).and_return(true)
145
151
  end
146
152
  end
153
+
147
154
  let(:server) { double("Mongo::Server") }
148
155
  let(:caching_cursor) { Mongo::CachingCursor.new(view, result, server) }
149
156
 
@@ -161,257 +168,268 @@ describe Mongo::QueryCache do
161
168
  allow(view).to receive(:limit) { nil }
162
169
  end
163
170
 
164
- context 'when there is no entry in the cache' do
165
- it 'returns nil' do
166
- expect(Mongo::QueryCache.get(**options)).to be_nil
167
- end
168
- end
169
-
170
- context 'when there is an entry in the cache' do
171
- before do
172
- Mongo::QueryCache.set(caching_cursor, **caching_cursor_options)
173
- end
174
-
175
- context 'when that entry has no limit' do
176
- let(:caching_cursor_options) do
177
- {
178
- namespace: 'db.coll',
179
- selector: { field: 'value' },
180
- }
181
- end
182
-
183
- let(:query_options) do
184
- caching_cursor_options.merge(limit: limit)
185
- end
186
-
187
- context 'when the query has a limit' do
188
- let(:limit) { 5 }
189
-
190
- it 'returns the caching cursor' do
191
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
192
- end
193
- end
194
-
195
- context 'when the query has a limit but negative' do
196
- let(:limit) { -5 }
197
-
198
- it 'returns the caching cursor' do
199
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
200
- end
201
- end
202
-
203
- context 'when the query has no limit' do
204
- let(:limit) { nil }
205
-
206
- it 'returns the caching cursor' do
207
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
208
- end
209
- end
210
-
211
- context 'when the query has a 0 limit' do
212
- let(:limit) { 0 }
213
-
214
- it 'returns the caching cursor' do
215
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
216
- end
217
- end
218
- end
219
-
220
- context 'when that entry has a 0 limit' do
221
- let(:caching_cursor_options) do
222
- {
223
- namespace: 'db.coll',
224
- selector: { field: 'value' },
225
- limit: 0,
226
- }
227
- end
228
-
229
- let(:query_options) do
230
- caching_cursor_options.merge(limit: limit)
231
- end
232
-
233
- before do
234
- allow(view).to receive(:limit) { 0 }
235
- end
236
-
237
- context 'when the query has a limit' do
238
- let(:limit) { 5 }
239
-
240
- it 'returns the caching cursor' do
241
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
242
- end
243
- end
244
-
245
- context 'when the query has a limit but negative' do
246
- let(:limit) { -5 }
247
-
248
- it 'returns the caching cursor' do
249
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
250
- end
251
- end
252
-
253
-
254
- context 'when the query has no limit' do
255
- let(:limit) { nil }
256
-
257
- it 'returns the caching cursor' do
258
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
259
- end
260
- end
261
-
262
- context 'when the query has a 0 limit' do
263
- let(:limit) { 0 }
264
-
265
- it 'returns the caching cursor' do
266
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
267
- end
268
- end
269
- end
270
-
271
- context 'when that entry has a limit' do
272
- let(:caching_cursor_options) do
273
- {
274
- namespace: 'db.coll',
275
- selector: { field: 'value' },
276
- limit: 5,
277
- }
278
- end
279
-
280
- let(:query_options) do
281
- caching_cursor_options.merge(limit: limit)
282
- end
283
-
171
+ [true, false].each do |load_balancer|
172
+ context "when load_balancer is #{load_balancer}" do
284
173
  before do
285
- allow(view).to receive(:limit) { 5 }
286
- end
287
-
288
- context 'and the new query has a smaller limit' do
289
- let(:limit) { 4 }
290
-
291
- it 'returns the caching cursor' do
292
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
293
- end
294
- end
295
-
296
- context 'and the new query has a smaller limit but negative' do
297
- let(:limit) { -4 }
298
-
299
- it 'returns the caching cursor' do
300
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
174
+ allow(server).to receive(:load_balancer?) { load_balancer }
175
+ if load_balancer
176
+ allow(result).to receive(:connection) { nil }
301
177
  end
302
178
  end
303
179
 
304
- context 'and the new query has a larger limit' do
305
- let(:limit) { 6 }
306
-
180
+ context 'when there is no entry in the cache' do
307
181
  it 'returns nil' do
308
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
182
+ expect(Mongo::QueryCache.get(**options)).to be_nil
309
183
  end
310
184
  end
311
185
 
312
- context 'and the new query has a larger limit but negative' do
313
- let(:limit) { -6 }
314
-
315
- it 'returns nil' do
316
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
317
- end
318
- end
319
-
320
- context 'and the new query has the same limit' do
321
- let(:limit) { 5 }
322
-
323
- it 'returns the caching cursor' do
324
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
325
- end
326
- end
327
-
328
- context 'and the new query has the same limit but negative' do
329
- let(:limit) { -5 }
330
-
331
- it 'returns the caching cursor' do
332
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
186
+ context 'when there is an entry in the cache' do
187
+ before do
188
+ Mongo::QueryCache.set(caching_cursor, **caching_cursor_options)
333
189
  end
334
- end
335
-
336
- context 'and the new query has no limit' do
337
- let(:limit) { nil }
338
190
 
339
- it 'returns nil' do
340
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
191
+ context 'when that entry has no limit' do
192
+ let(:caching_cursor_options) do
193
+ {
194
+ namespace: 'db.coll',
195
+ selector: { field: 'value' },
196
+ }
197
+ end
198
+
199
+ let(:query_options) do
200
+ caching_cursor_options.merge(limit: limit)
201
+ end
202
+
203
+ context 'when the query has a limit' do
204
+ let(:limit) { 5 }
205
+
206
+ it 'returns the caching cursor' do
207
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
208
+ end
209
+ end
210
+
211
+ context 'when the query has a limit but negative' do
212
+ let(:limit) { -5 }
213
+
214
+ it 'returns the caching cursor' do
215
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
216
+ end
217
+ end
218
+
219
+ context 'when the query has no limit' do
220
+ let(:limit) { nil }
221
+
222
+ it 'returns the caching cursor' do
223
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
224
+ end
225
+ end
226
+
227
+ context 'when the query has a 0 limit' do
228
+ let(:limit) { 0 }
229
+
230
+ it 'returns the caching cursor' do
231
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
232
+ end
233
+ end
341
234
  end
342
- end
343
235
 
344
- context 'and the new query has a 0 limit' do
345
- let(:limit) { 0 }
236
+ context 'when that entry has a 0 limit' do
237
+ let(:caching_cursor_options) do
238
+ {
239
+ namespace: 'db.coll',
240
+ selector: { field: 'value' },
241
+ limit: 0,
242
+ }
243
+ end
346
244
 
347
- it 'returns nil' do
348
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
349
- end
350
- end
351
- end
352
-
353
- context 'when that entry has a negative limit' do
354
- let(:caching_cursor_options) do
355
- {
356
- namespace: 'db.coll',
357
- selector: { field: 'value' },
358
- limit: -5,
359
- }
360
- end
245
+ let(:query_options) do
246
+ caching_cursor_options.merge(limit: limit)
247
+ end
361
248
 
362
- let(:query_options) do
363
- caching_cursor_options.merge(limit: limit)
364
- end
249
+ before do
250
+ allow(view).to receive(:limit) { 0 }
251
+ end
365
252
 
366
- before do
367
- allow(view).to receive(:limit) { -5 }
368
- end
253
+ context 'when the query has a limit' do
254
+ let(:limit) { 5 }
369
255
 
370
- context 'and the new query has a smaller limit' do
371
- let(:limit) { 4 }
256
+ it 'returns the caching cursor' do
257
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
258
+ end
259
+ end
372
260
 
373
- it 'returns the caching cursor' do
374
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
375
- end
376
- end
261
+ context 'when the query has a limit but negative' do
262
+ let(:limit) { -5 }
377
263
 
378
- context 'and the new query has a larger limit' do
379
- let(:limit) { 6 }
264
+ it 'returns the caching cursor' do
265
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
266
+ end
267
+ end
380
268
 
381
- it 'returns nil' do
382
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
383
- end
384
- end
385
269
 
386
- context 'and the new query has the same negative limit' do
387
- let(:limit) { -5 }
270
+ context 'when the query has no limit' do
271
+ let(:limit) { nil }
388
272
 
389
- it 'returns the caching cursor' do
390
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
391
- end
392
- end
273
+ it 'returns the caching cursor' do
274
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
275
+ end
276
+ end
393
277
 
394
- context 'and the new query has the same positive limit' do
395
- let(:limit) { 5 }
278
+ context 'when the query has a 0 limit' do
279
+ let(:limit) { 0 }
396
280
 
397
- it 'returns the caching cursor' do
398
- expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
281
+ it 'returns the caching cursor' do
282
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
283
+ end
284
+ end
399
285
  end
400
- end
401
-
402
- context 'and the new query has no limit' do
403
- let(:limit) { nil }
404
286
 
405
- it 'returns nil' do
406
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
287
+ context 'when that entry has a limit' do
288
+ let(:caching_cursor_options) do
289
+ {
290
+ namespace: 'db.coll',
291
+ selector: { field: 'value' },
292
+ limit: 5,
293
+ }
294
+ end
295
+
296
+ let(:query_options) do
297
+ caching_cursor_options.merge(limit: limit)
298
+ end
299
+
300
+ before do
301
+ allow(view).to receive(:limit) { 5 }
302
+ end
303
+
304
+ context 'and the new query has a smaller limit' do
305
+ let(:limit) { 4 }
306
+
307
+ it 'returns the caching cursor' do
308
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
309
+ end
310
+ end
311
+
312
+ context 'and the new query has a smaller limit but negative' do
313
+ let(:limit) { -4 }
314
+
315
+ it 'returns the caching cursor' do
316
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
317
+ end
318
+ end
319
+
320
+ context 'and the new query has a larger limit' do
321
+ let(:limit) { 6 }
322
+
323
+ it 'returns nil' do
324
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
325
+ end
326
+ end
327
+
328
+ context 'and the new query has a larger limit but negative' do
329
+ let(:limit) { -6 }
330
+
331
+ it 'returns nil' do
332
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
333
+ end
334
+ end
335
+
336
+ context 'and the new query has the same limit' do
337
+ let(:limit) { 5 }
338
+
339
+ it 'returns the caching cursor' do
340
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
341
+ end
342
+ end
343
+
344
+ context 'and the new query has the same limit but negative' do
345
+ let(:limit) { -5 }
346
+
347
+ it 'returns the caching cursor' do
348
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
349
+ end
350
+ end
351
+
352
+ context 'and the new query has no limit' do
353
+ let(:limit) { nil }
354
+
355
+ it 'returns nil' do
356
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
357
+ end
358
+ end
359
+
360
+ context 'and the new query has a 0 limit' do
361
+ let(:limit) { 0 }
362
+
363
+ it 'returns nil' do
364
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
365
+ end
366
+ end
407
367
  end
408
- end
409
-
410
- context 'and the new query has a 0 limit' do
411
- let(:limit) { 0 }
412
368
 
413
- it 'returns nil' do
414
- expect(Mongo::QueryCache.get(**query_options)).to be_nil
369
+ context 'when that entry has a negative limit' do
370
+ let(:caching_cursor_options) do
371
+ {
372
+ namespace: 'db.coll',
373
+ selector: { field: 'value' },
374
+ limit: -5,
375
+ }
376
+ end
377
+
378
+ let(:query_options) do
379
+ caching_cursor_options.merge(limit: limit)
380
+ end
381
+
382
+ before do
383
+ allow(view).to receive(:limit) { -5 }
384
+ end
385
+
386
+ context 'and the new query has a smaller limit' do
387
+ let(:limit) { 4 }
388
+
389
+ it 'returns the caching cursor' do
390
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
391
+ end
392
+ end
393
+
394
+ context 'and the new query has a larger limit' do
395
+ let(:limit) { 6 }
396
+
397
+ it 'returns nil' do
398
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
399
+ end
400
+ end
401
+
402
+ context 'and the new query has the same negative limit' do
403
+ let(:limit) { -5 }
404
+
405
+ it 'returns the caching cursor' do
406
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
407
+ end
408
+ end
409
+
410
+ context 'and the new query has the same positive limit' do
411
+ let(:limit) { 5 }
412
+
413
+ it 'returns the caching cursor' do
414
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
415
+ end
416
+ end
417
+
418
+ context 'and the new query has no limit' do
419
+ let(:limit) { nil }
420
+
421
+ it 'returns nil' do
422
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
423
+ end
424
+ end
425
+
426
+ context 'and the new query has a 0 limit' do
427
+ let(:limit) { 0 }
428
+
429
+ it 'returns nil' do
430
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
431
+ end
432
+ end
415
433
  end
416
434
  end
417
435
  end
@@ -76,6 +76,7 @@ class ModernRetryableTestConsumer < LegacyRetryableTestConsumer
76
76
  allow(session).to receive(:pinned_connection_global_id)
77
77
  allow(session).to receive(:starting_transaction?).and_return(false)
78
78
  allow(session).to receive(:materialize)
79
+ allow(session).to receive(:with_transaction_deadline).and_return(nil)
79
80
  end
80
81
  end
81
82
 
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Mongo::Server::RoundTripTimeCalculator do
7
+ let(:calculator) { Mongo::Server::RoundTripTimeCalculator.new }
8
+
9
+ describe '#update_average_round_trip_time' do
10
+ context 'no existing average rtt' do
11
+ it 'updates average rtt' do
12
+ calculator.instance_variable_set('@last_round_trip_time', 5)
13
+ calculator.update_average_round_trip_time
14
+ expect(calculator.average_round_trip_time).to eq(5)
15
+ end
16
+ end
17
+
18
+ context 'with existing average rtt' do
19
+ it 'averages with existing average rtt' do
20
+ calculator.instance_variable_set('@last_round_trip_time', 5)
21
+ calculator.instance_variable_set('@average_round_trip_time', 10)
22
+ calculator.update_average_round_trip_time
23
+ expect(calculator.average_round_trip_time).to eq(9)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#update_minimum_round_trip_time' do
29
+ context 'with no samples' do
30
+ it 'sets minimum_round_trip_time to zero' do
31
+ calculator.update_minimum_round_trip_time
32
+ expect(calculator.minimum_round_trip_time).to eq(0)
33
+ end
34
+ end
35
+
36
+ context 'with one sample' do
37
+ before do
38
+ calculator.instance_variable_set('@last_round_trip_time', 5)
39
+ end
40
+
41
+ it 'sets minimum_round_trip_time to zero' do
42
+ calculator.update_minimum_round_trip_time
43
+ expect(calculator.minimum_round_trip_time).to eq(0)
44
+ end
45
+ end
46
+
47
+ context 'with two samples' do
48
+ before do
49
+ calculator.instance_variable_set('@last_round_trip_time', 10)
50
+ calculator.instance_variable_set('@rtts', [5])
51
+ end
52
+
53
+ it 'sets minimum_round_trip_time to zero' do
54
+ calculator.update_minimum_round_trip_time
55
+ expect(calculator.minimum_round_trip_time).to eq(0)
56
+ end
57
+ end
58
+
59
+ context 'with samples less than maximum' do
60
+ before do
61
+ calculator.instance_variable_set('@last_round_trip_time', 10)
62
+ calculator.instance_variable_set('@rtts', [5, 4, 120])
63
+ end
64
+
65
+ it 'properly sets minimum_round_trip_time' do
66
+ calculator.update_minimum_round_trip_time
67
+ expect(calculator.minimum_round_trip_time).to eq(4)
68
+ end
69
+ end
70
+
71
+ context 'with more than maximum samples' do
72
+ before do
73
+ calculator.instance_variable_set('@last_round_trip_time', 2)
74
+ calculator.instance_variable_set('@rtts', [1, 20, 15, 4, 5, 6, 7, 39, 8, 4])
75
+ end
76
+
77
+ it 'properly sets minimum_round_trip_time' do
78
+ calculator.update_minimum_round_trip_time
79
+ expect(calculator.minimum_round_trip_time).to eq(2)
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ describe '#measure' do
86
+ context 'block does not raise' do
87
+ it 'updates average rtt' do
88
+ expect(calculator).to receive(:update_average_round_trip_time)
89
+ calculator.measure do
90
+ end
91
+ end
92
+
93
+ it 'updates minimum rtt' do
94
+ expect(calculator).to receive(:update_minimum_round_trip_time)
95
+ calculator.measure do
96
+ end
97
+ end
98
+ end
99
+
100
+ context 'block raises' do
101
+ it 'does not update average rtt' do
102
+ expect(calculator).not_to receive(:update_average_round_trip_time)
103
+ expect do
104
+ calculator.measure do
105
+ raise "Problem"
106
+ end
107
+ end.to raise_error(/Problem/)
108
+ end
109
+
110
+ it 'does not update minimum rtt' do
111
+ expect(calculator).not_to receive(:update_minimum_round_trip_time)
112
+ expect do
113
+ calculator.measure do
114
+ raise "Problem"
115
+ end
116
+ end.to raise_error(/Problem/)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -103,16 +103,6 @@ describe Mongo::Socket::SSL do
103
103
  expect(socket).to be_alive
104
104
  end
105
105
  end
106
-
107
- context 'when connecting the tcp socket raises an exception' do
108
-
109
- it 'raises an exception' do
110
- expect_any_instance_of(::Socket).to receive(:connect).and_raise(Mongo::Error::SocketTimeoutError)
111
- expect do
112
- socket
113
- end.to raise_error(Mongo::Error::SocketTimeoutError)
114
- end
115
- end
116
106
  end
117
107
 
118
108
  context 'when a certificate and key are provided as strings' do
@@ -111,7 +111,7 @@ module Mongo
111
111
  def run
112
112
  change_stream = begin
113
113
  @target.watch(@pipeline, ::Utils.snakeize_hash(@options))
114
- rescue Mongo::Error::OperationFailure => e
114
+ rescue Mongo::Error::OperationFailure::Family => e
115
115
  return {
116
116
  result: {
117
117
  error: {
@@ -146,7 +146,7 @@ module Mongo
146
146
  begin
147
147
  change = enum.next
148
148
  changes << change
149
- rescue Mongo::Error::OperationFailure => e
149
+ rescue Mongo::Error::OperationFailure::Family => e
150
150
  return {
151
151
  result: {
152
152
  error: {
@@ -355,7 +355,7 @@ module Mongo
355
355
  if coll.indexes.map { |doc| doc['name'] }.include?(ixn = arguments.fetch('index'))
356
356
  raise "Index #{ixn} exists in collection #{cn} in database #{dn}, but must not"
357
357
  end
358
- rescue Mongo::Error::OperationFailure => e
358
+ rescue Mongo::Error::OperationFailure::Family => e
359
359
  if e.to_s =~ /ns does not exist/
360
360
  # Success.
361
361
  else