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
@@ -18,242 +18,247 @@ require 'mongo/error/read_write_retryable'
18
18
 
19
19
  module Mongo
20
20
  class Error
21
-
22
21
  # Raised when an operation fails for some reason.
23
- #
24
- # @since 2.0.0
25
22
  class OperationFailure < Error
26
- extend Forwardable
27
- include SdamErrorDetection
28
- include ReadWriteRetryable
23
+ # Implements the behavior for an OperationFailure error. Other errors
24
+ # (e.g. ServerTimeoutError) may also implement this, so that they may
25
+ # be recognized and treated as OperationFailure errors.
26
+ module OperationFailure::Family
27
+ extend Forwardable
28
+ include SdamErrorDetection
29
+ include ReadWriteRetryable
29
30
 
30
- def_delegators :@result, :operation_time
31
+ def_delegators :@result, :operation_time
31
32
 
32
- # @!method connection_description
33
- #
34
- # @return [ Server::Description ] Server description of the server that
35
- # the operation that this exception refers to was performed on.
36
- #
37
- # @api private
38
- def_delegator :@result, :connection_description
33
+ # @!method connection_description
34
+ #
35
+ # @return [ Server::Description ] Server description of the server that
36
+ # the operation that this exception refers to was performed on.
37
+ #
38
+ # @api private
39
+ def_delegator :@result, :connection_description
39
40
 
40
- # @return [ Integer ] The error code parsed from the document.
41
- #
42
- # @since 2.6.0
43
- attr_reader :code
41
+ # @return [ Integer ] The error code parsed from the document.
42
+ #
43
+ # @since 2.6.0
44
+ attr_reader :code
44
45
 
45
- # @return [ String ] The error code name parsed from the document.
46
- #
47
- # @since 2.6.0
48
- attr_reader :code_name
46
+ # @return [ String ] The error code name parsed from the document.
47
+ #
48
+ # @since 2.6.0
49
+ attr_reader :code_name
49
50
 
50
- # @return [ String ] The server-returned error message
51
- # parsed from the response.
52
- #
53
- # @api experimental
54
- attr_reader :server_message
51
+ # @return [ String ] The server-returned error message
52
+ # parsed from the response.
53
+ #
54
+ # @api experimental
55
+ attr_reader :server_message
55
56
 
56
- # Error codes and code names that should result in a failing getMore
57
- # command on a change stream NOT being resumed.
58
- #
59
- # @api private
60
- CHANGE_STREAM_RESUME_ERRORS = [
61
- {code_name: 'HostUnreachable', code: 6},
62
- {code_name: 'HostNotFound', code: 7},
63
- {code_name: 'NetworkTimeout', code: 89},
64
- {code_name: 'ShutdownInProgress', code: 91},
65
- {code_name: 'PrimarySteppedDown', code: 189},
66
- {code_name: 'ExceededTimeLimit', code: 262},
67
- {code_name: 'SocketException', code: 9001},
68
- {code_name: 'NotMaster', code: 10107},
69
- {code_name: 'InterruptedAtShutdown', code: 11600},
70
- {code_name: 'InterruptedDueToReplStateChange', code: 11602},
71
- {code_name: 'NotPrimaryNoSecondaryOk', code: 13435},
72
- {code_name: 'NotMasterOrSecondary', code: 13436},
57
+ # Error codes and code names that should result in a failing getMore
58
+ # command on a change stream NOT being resumed.
59
+ #
60
+ # @api private
61
+ CHANGE_STREAM_RESUME_ERRORS = [
62
+ {code_name: 'HostUnreachable', code: 6},
63
+ {code_name: 'HostNotFound', code: 7},
64
+ {code_name: 'NetworkTimeout', code: 89},
65
+ {code_name: 'ShutdownInProgress', code: 91},
66
+ {code_name: 'PrimarySteppedDown', code: 189},
67
+ {code_name: 'ExceededTimeLimit', code: 262},
68
+ {code_name: 'SocketException', code: 9001},
69
+ {code_name: 'NotMaster', code: 10107},
70
+ {code_name: 'InterruptedAtShutdown', code: 11600},
71
+ {code_name: 'InterruptedDueToReplStateChange', code: 11602},
72
+ {code_name: 'NotPrimaryNoSecondaryOk', code: 13435},
73
+ {code_name: 'NotMasterOrSecondary', code: 13436},
73
74
 
74
- {code_name: 'StaleShardVersion', code: 63},
75
- {code_name: 'FailedToSatisfyReadPreference', code: 133},
76
- {code_name: 'StaleEpoch', code: 150},
77
- {code_name: 'RetryChangeStream', code: 234},
78
- {code_name: 'StaleConfig', code: 13388},
79
- ].freeze
75
+ {code_name: 'StaleShardVersion', code: 63},
76
+ {code_name: 'FailedToSatisfyReadPreference', code: 133},
77
+ {code_name: 'StaleEpoch', code: 150},
78
+ {code_name: 'RetryChangeStream', code: 234},
79
+ {code_name: 'StaleConfig', code: 13388},
80
+ ].freeze
80
81
 
81
- # Change stream can be resumed when these error messages are encountered.
82
- #
83
- # @since 2.6.0
84
- # @api private
85
- CHANGE_STREAM_RESUME_MESSAGES = ReadWriteRetryable::WRITE_RETRY_MESSAGES
82
+ # Change stream can be resumed when these error messages are encountered.
83
+ #
84
+ # @since 2.6.0
85
+ # @api private
86
+ CHANGE_STREAM_RESUME_MESSAGES = ReadWriteRetryable::WRITE_RETRY_MESSAGES
86
87
 
87
- # Can the change stream on which this error occurred be resumed,
88
- # provided the operation that triggered this error was a getMore?
89
- #
90
- # @example Is the error resumable for the change stream?
91
- # error.change_stream_resumable?
92
- #
93
- # @return [ true, false ] Whether the error is resumable.
94
- #
95
- # @since 2.6.0
96
- def change_stream_resumable?
97
- if @result && @result.is_a?(Mongo::Operation::GetMore::Result)
98
- # CursorNotFound exceptions are always resumable because the server
99
- # is not aware of the cursor id, and thus cannot determine if
100
- # the cursor is a change stream and cannot add the
101
- # ResumableChangeStreamError label.
102
- return true if code == 43
88
+ # Can the change stream on which this error occurred be resumed,
89
+ # provided the operation that triggered this error was a getMore?
90
+ #
91
+ # @example Is the error resumable for the change stream?
92
+ # error.change_stream_resumable?
93
+ #
94
+ # @return [ true, false ] Whether the error is resumable.
95
+ #
96
+ # @since 2.6.0
97
+ def change_stream_resumable?
98
+ if @result && @result.is_a?(Mongo::Operation::GetMore::Result)
99
+ # CursorNotFound exceptions are always resumable because the server
100
+ # is not aware of the cursor id, and thus cannot determine if
101
+ # the cursor is a change stream and cannot add the
102
+ # ResumableChangeStreamError label.
103
+ return true if code == 43
103
104
 
104
- # Connection description is not populated for unacknowledged writes.
105
- if connection_description.max_wire_version >= 9
106
- label?('ResumableChangeStreamError')
105
+ # Connection description is not populated for unacknowledged writes.
106
+ if connection_description.max_wire_version >= 9
107
+ label?('ResumableChangeStreamError')
108
+ else
109
+ change_stream_resumable_code?
110
+ end
107
111
  else
108
- change_stream_resumable_code?
112
+ false
109
113
  end
110
- else
111
- false
112
114
  end
113
- end
114
115
 
115
- def change_stream_resumable_code?
116
- CHANGE_STREAM_RESUME_ERRORS.any? { |e| e[:code] == code }
117
- end
118
- private :change_stream_resumable_code?
116
+ def change_stream_resumable_code?
117
+ CHANGE_STREAM_RESUME_ERRORS.any? { |e| e[:code] == code }
118
+ end
119
+ private :change_stream_resumable_code?
119
120
 
120
- # @return [ true | false ] Whether the failure includes a write
121
- # concern error. A failure may have a top level error and a write
122
- # concern error or either one of the two.
123
- #
124
- # @since 2.10.0
125
- def write_concern_error?
126
- !!@write_concern_error_document
127
- end
121
+ # @return [ true | false ] Whether the failure includes a write
122
+ # concern error. A failure may have a top level error and a write
123
+ # concern error or either one of the two.
124
+ #
125
+ # @since 2.10.0
126
+ def write_concern_error?
127
+ !!@write_concern_error_document
128
+ end
128
129
 
129
- # Returns the write concern error document as it was reported by the
130
- # server, if any.
131
- #
132
- # @return [ Hash | nil ] Write concern error as reported to the server.
133
- attr_reader :write_concern_error_document
130
+ # Returns the write concern error document as it was reported by the
131
+ # server, if any.
132
+ #
133
+ # @return [ Hash | nil ] Write concern error as reported to the server.
134
+ attr_reader :write_concern_error_document
134
135
 
135
- # @return [ Integer | nil ] The error code for the write concern error,
136
- # if a write concern error is present and has a code.
137
- #
138
- # @since 2.10.0
139
- attr_reader :write_concern_error_code
136
+ # @return [ Integer | nil ] The error code for the write concern error,
137
+ # if a write concern error is present and has a code.
138
+ #
139
+ # @since 2.10.0
140
+ attr_reader :write_concern_error_code
140
141
 
141
- # @return [ String | nil ] The code name for the write concern error,
142
- # if a write concern error is present and has a code name.
143
- #
144
- # @since 2.10.0
145
- attr_reader :write_concern_error_code_name
142
+ # @return [ String | nil ] The code name for the write concern error,
143
+ # if a write concern error is present and has a code name.
144
+ #
145
+ # @since 2.10.0
146
+ attr_reader :write_concern_error_code_name
146
147
 
147
- # @return [ String | nil ] The details of the error.
148
- # For WriteConcernErrors this is `document['writeConcernError']['errInfo']`.
149
- # For WriteErrors this is `document['writeErrors'][0]['errInfo']`.
150
- # For all other errors this is nil.
151
- attr_reader :details
148
+ # @return [ String | nil ] The details of the error.
149
+ # For WriteConcernErrors this is `document['writeConcernError']['errInfo']`.
150
+ # For WriteErrors this is `document['writeErrors'][0]['errInfo']`.
151
+ # For all other errors this is nil.
152
+ attr_reader :details
152
153
 
153
- # @return [ BSON::Document | nil ] The server-returned error document.
154
- #
155
- # @api experimental
156
- attr_reader :document
154
+ # @return [ BSON::Document | nil ] The server-returned error document.
155
+ #
156
+ # @api experimental
157
+ attr_reader :document
157
158
 
158
- # Create the operation failure.
159
- #
160
- # @example Create the error object
161
- # OperationFailure.new(message, result)
162
- #
163
- # @example Create the error object with a code and a code name
164
- # OperationFailure.new(message, result, :code => code, :code_name => code_name)
165
- #
166
- # @param [ String ] message The error message.
167
- # @param [ Operation::Result ] result The result object.
168
- # @param [ Hash ] options Additional parameters.
169
- #
170
- # @option options [ Integer ] :code Error code.
171
- # @option options [ String ] :code_name Error code name.
172
- # @option options [ BSON::Document ] :document The server-returned
173
- # error document.
174
- # @option options [ String ] server_message The server-returned
175
- # error message parsed from the response.
176
- # @option options [ Hash ] :write_concern_error_document The
177
- # server-supplied write concern error document, if any.
178
- # @option options [ Integer ] :write_concern_error_code Error code for
179
- # write concern error, if any.
180
- # @option options [ String ] :write_concern_error_code_name Error code
181
- # name for write concern error, if any.
182
- # @option options [ Array<String> ] :write_concern_error_labels Error
183
- # labels for the write concern error, if any.
184
- # @option options [ Array<String> ] :labels The set of labels associated
185
- # with the error.
186
- # @option options [ true | false ] :wtimeout Whether the error is a wtimeout.
187
- def initialize(message = nil, result = nil, options = {})
188
- @details = retrieve_details(options[:document])
189
- super(append_details(message, @details))
159
+ # @return [ Operation::Result ] the result object for the operation.
160
+ #
161
+ # @api private
162
+ attr_reader :result
190
163
 
191
- @result = result
192
- @code = options[:code]
193
- @code_name = options[:code_name]
194
- @write_concern_error_document = options[:write_concern_error_document]
195
- @write_concern_error_code = options[:write_concern_error_code]
196
- @write_concern_error_code_name = options[:write_concern_error_code_name]
197
- @write_concern_error_labels = options[:write_concern_error_labels] || []
198
- @labels = options[:labels] || []
199
- @wtimeout = !!options[:wtimeout]
200
- @document = options[:document]
201
- @server_message = options[:server_message]
202
- end
164
+ # Create the operation failure.
165
+ #
166
+ # @param [ String ] message The error message.
167
+ # @param [ Operation::Result ] result The result object.
168
+ # @param [ Hash ] options Additional parameters.
169
+ #
170
+ # @option options [ Integer ] :code Error code.
171
+ # @option options [ String ] :code_name Error code name.
172
+ # @option options [ BSON::Document ] :document The server-returned
173
+ # error document.
174
+ # @option options [ String ] server_message The server-returned
175
+ # error message parsed from the response.
176
+ # @option options [ Hash ] :write_concern_error_document The
177
+ # server-supplied write concern error document, if any.
178
+ # @option options [ Integer ] :write_concern_error_code Error code for
179
+ # write concern error, if any.
180
+ # @option options [ String ] :write_concern_error_code_name Error code
181
+ # name for write concern error, if any.
182
+ # @option options [ Array<String> ] :write_concern_error_labels Error
183
+ # labels for the write concern error, if any.
184
+ # @option options [ Array<String> ] :labels The set of labels associated
185
+ # with the error.
186
+ # @option options [ true | false ] :wtimeout Whether the error is a wtimeout.
187
+ def initialize(message = nil, result = nil, options = {})
188
+ @details = retrieve_details(options[:document])
189
+ super(append_details(message, @details))
203
190
 
204
- # Whether the error is a write concern timeout.
205
- #
206
- # @return [ true | false ] Whether the error is a write concern timeout.
207
- #
208
- # @since 2.7.1
209
- def wtimeout?
210
- @wtimeout
211
- end
191
+ @result = result
192
+ @code = options[:code]
193
+ @code_name = options[:code_name]
194
+ @write_concern_error_document = options[:write_concern_error_document]
195
+ @write_concern_error_code = options[:write_concern_error_code]
196
+ @write_concern_error_code_name = options[:write_concern_error_code_name]
197
+ @write_concern_error_labels = options[:write_concern_error_labels] || []
198
+ @labels = options[:labels] || []
199
+ @wtimeout = !!options[:wtimeout]
200
+ @document = options[:document]
201
+ @server_message = options[:server_message]
202
+ end
212
203
 
213
- # Whether the error is MaxTimeMSExpired.
214
- #
215
- # @return [ true | false ] Whether the error is MaxTimeMSExpired.
216
- #
217
- # @since 2.10.0
218
- def max_time_ms_expired?
219
- code == 50 # MaxTimeMSExpired
220
- end
204
+ # Whether the error is a write concern timeout.
205
+ #
206
+ # @return [ true | false ] Whether the error is a write concern timeout.
207
+ #
208
+ # @since 2.7.1
209
+ def wtimeout?
210
+ @wtimeout
211
+ end
221
212
 
222
- # Whether the error is caused by an attempted retryable write
223
- # on a storage engine that does not support retryable writes.
224
- #
225
- # @return [ true | false ] Whether the error is caused by an attempted
226
- # retryable write on a storage engine that does not support retryable writes.
227
- #
228
- # @since 2.10.0
229
- def unsupported_retryable_write?
230
- # code 20 is IllegalOperation.
231
- # Note that the document is expected to be a BSON::Document, thus
232
- # either having string keys or providing indifferent access.
233
- code == 20 && server_message&.start_with?("Transaction numbers") || false
234
- end
213
+ # Whether the error is MaxTimeMSExpired.
214
+ #
215
+ # @return [ true | false ] Whether the error is MaxTimeMSExpired.
216
+ #
217
+ # @since 2.10.0
218
+ def max_time_ms_expired?
219
+ code == 50 # MaxTimeMSExpired
220
+ end
221
+
222
+ # Whether the error is caused by an attempted retryable write
223
+ # on a storage engine that does not support retryable writes.
224
+ #
225
+ # @return [ true | false ] Whether the error is caused by an attempted
226
+ # retryable write on a storage engine that does not support retryable writes.
227
+ #
228
+ # @since 2.10.0
229
+ def unsupported_retryable_write?
230
+ # code 20 is IllegalOperation.
231
+ # Note that the document is expected to be a BSON::Document, thus
232
+ # either having string keys or providing indifferent access.
233
+ code == 20 && server_message&.start_with?("Transaction numbers") || false
234
+ end
235
235
 
236
- private
236
+ private
237
237
 
238
- # Retrieve the details from a document
239
- #
240
- # @return [ Hash | nil ] the details extracted from the document
241
- def retrieve_details(document)
242
- return nil unless document
243
- if wce = document['writeConcernError']
244
- return wce['errInfo']
245
- elsif we = document['writeErrors']&.first
246
- return we['errInfo']
238
+ # Retrieve the details from a document
239
+ #
240
+ # @return [ Hash | nil ] the details extracted from the document
241
+ def retrieve_details(document)
242
+ return nil unless document
243
+ if wce = document['writeConcernError']
244
+ return wce['errInfo']
245
+ elsif we = document['writeErrors']&.first
246
+ return we['errInfo']
247
+ end
247
248
  end
248
- end
249
249
 
250
- # Append the details to the message
251
- #
252
- # @return [ String ] the message with the details appended to it
253
- def append_details(message, details)
254
- return message unless details && message
255
- message + " -- #{details.to_json}"
250
+ # Append the details to the message
251
+ #
252
+ # @return [ String ] the message with the details appended to it
253
+ def append_details(message, details)
254
+ return message unless details && message
255
+ message + " -- #{details.to_json}"
256
+ end
256
257
  end
258
+
259
+ # OperationFailure is the canonical implementor of the
260
+ # OperationFailure::Family concern.
261
+ include OperationFailure::Family
257
262
  end
258
263
  end
259
264
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongo/error/timeout_error'
4
+
5
+ module Mongo
6
+ class Error
7
+ # Raised when the server returns error code 50.
8
+ class ServerTimeoutError < TimeoutError
9
+ include OperationFailure::Family
10
+ end
11
+ end
12
+ end
@@ -15,13 +15,15 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+ require 'mongo/error/timeout_error'
19
+
18
20
  module Mongo
19
21
  class Error
20
22
 
21
23
  # Raised when a socket connection times out.
22
24
  #
23
25
  # @since 2.0.0
24
- class SocketTimeoutError < Error
26
+ class SocketTimeoutError < TimeoutError
25
27
  include WriteRetryable
26
28
  include ChangeStreamResumable
27
29
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2015-present MongoDB Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Mongo
18
+ class Error
19
+ # Raised when a Client Side Operation Timeout times out.
20
+ class TimeoutError < Error
21
+ end
22
+ end
23
+ end
data/lib/mongo/error.rb CHANGED
@@ -217,7 +217,9 @@ require 'mongo/error/missing_service_id'
217
217
  require 'mongo/error/server_api_conflict'
218
218
  require 'mongo/error/server_api_not_supported'
219
219
  require 'mongo/error/server_not_usable'
220
+ require 'mongo/error/server_timeout_error'
220
221
  require 'mongo/error/transactions_not_supported'
222
+ require 'mongo/error/timeout_error'
221
223
  require 'mongo/error/unknown_payload_type'
222
224
  require 'mongo/error/unmet_dependency'
223
225
  require 'mongo/error/unsupported_option'
@@ -201,8 +201,8 @@ module Mongo
201
201
  # @return [ Result ] The result of the remove.
202
202
  #
203
203
  # @since 2.0.0
204
- def delete_one(file)
205
- delete(file.id)
204
+ def delete_one(file, opts = {})
205
+ delete(file.id, opts)
206
206
  end
207
207
 
208
208
  # Remove a single file, identified by its id from the GridFS.
@@ -217,9 +217,14 @@ module Mongo
217
217
  # @raise [ Error::FileNotFound ] If the file is not found.
218
218
  #
219
219
  # @since 2.1.0
220
- def delete(id)
221
- result = files_collection.find({ :_id => id }, @options).delete_one
222
- chunks_collection.find({ :files_id => id }, @options).delete_many
220
+ def delete(id, opts = {})
221
+ timeout_holder = CsotTimeoutHolder.new(operation_timeouts: operation_timeouts(opts))
222
+ result = files_collection
223
+ .find({ :_id => id }, @options.merge(timeout_ms: timeout_holder.remaining_timeout_ms))
224
+ .delete_one(timeout_ms: timeout_holder.remaining_timeout_ms)
225
+ chunks_collection
226
+ .find({ :files_id => id }, @options.merge(timeout_ms: timeout_holder.remaining_timeout_ms))
227
+ .delete_many(timeout_ms: timeout_holder.remaining_timeout_ms)
223
228
  raise Error::FileNotFound.new(id, :id) if result.n == 0
224
229
  result
225
230
  end
@@ -485,9 +490,10 @@ module Mongo
485
490
  end
486
491
 
487
492
  # Drop the collections that implement this bucket.
488
- def drop
489
- files_collection.drop
490
- chunks_collection.drop
493
+ def drop(opts = {})
494
+ context = Operation::Context.new(operation_timeouts: operation_timeouts(opts))
495
+ files_collection.drop(timeout_ms: context.remaining_timeout_ms)
496
+ chunks_collection.drop(timeout_ms: context.remaining_timeout_ms)
491
497
  end
492
498
 
493
499
  private
@@ -512,12 +518,24 @@ module Mongo
512
518
  "#{prefix}.#{Grid::File::Info::COLLECTION}"
513
519
  end
514
520
 
515
- def ensure_indexes!
516
- if files_collection.find({}, limit: 1, projection: { _id: 1 }).first.nil?
521
+ def ensure_indexes!(timeout_holder = nil)
522
+ fc_idx = files_collection.find(
523
+ {},
524
+ limit: 1,
525
+ projection: { _id: 1 },
526
+ timeout_ms: timeout_holder&.remaining_timeout_ms
527
+ ).first
528
+ if fc_idx.nil?
517
529
  create_index_if_missing!(files_collection, FSBucket::FILES_INDEX)
518
530
  end
519
531
 
520
- if chunks_collection.find({}, limit: 1, projection: { _id: 1 }).first.nil?
532
+ cc_idx = chunks_collection.find(
533
+ {},
534
+ limit: 1,
535
+ projection: { _id: 1 },
536
+ timeout_ms: timeout_holder&.remaining_timeout_ms
537
+ ).first
538
+ if cc_idx.nil?
521
539
  create_index_if_missing!(chunks_collection, FSBucket::CHUNKS_INDEX, :unique => true)
522
540
  end
523
541
  end
@@ -528,7 +546,7 @@ module Mongo
528
546
  if indexes_view.get(index_spec).nil?
529
547
  indexes_view.create_one(index_spec, options)
530
548
  end
531
- rescue Mongo::Error::OperationFailure => e
549
+ rescue Mongo::Error::OperationFailure::Family => e
532
550
  # proceed with index creation if a NamespaceNotFound error is thrown
533
551
  if e.code == 26
534
552
  indexes_view.create_one(index_spec, options)
@@ -537,6 +555,21 @@ module Mongo
537
555
  end
538
556
  end
539
557
  end
558
+
559
+ # @return [ Hash ] timeout_ms value set on the operation level (if any),
560
+ # and/or timeout_ms that is set on collection/database/client level (if any).
561
+ #
562
+ # @api private
563
+ def operation_timeouts(opts = {})
564
+ # TODO: We should re-evaluate if we need two timeouts separately.
565
+ {}.tap do |result|
566
+ if opts[:timeout_ms].nil?
567
+ result[:inherited_timeout_ms] = database.timeout_ms
568
+ else
569
+ result[:operation_timeout_ms] = opts[:timeout_ms]
570
+ end
571
+ end
572
+ end
540
573
  end
541
574
  end
542
575
  end
@@ -59,6 +59,12 @@ module Mongo
59
59
  @file_id = @options.delete(:file_id)
60
60
  @options.freeze
61
61
  @open = true
62
+ @timeout_holder = CsotTimeoutHolder.new(
63
+ operation_timeouts: {
64
+ operation_timeout_ms: options[:timeout_ms],
65
+ inherited_timeout_ms: fs.database.timeout_ms
66
+ }
67
+ )
62
68
  end
63
69
 
64
70
  # Iterate through chunk data streamed from the FSBucket.
@@ -178,7 +184,11 @@ module Mongo
178
184
  # @since 2.1.0
179
185
  def file_info
180
186
  @file_info ||= begin
181
- doc = options[:file_info_doc] || fs.files_collection.find(_id: file_id).first
187
+ doc = options[:file_info_doc] ||
188
+ fs.files_collection.find(
189
+ { _id: file_id },
190
+ { timeout_ms: @timeout_holder.remaining_timeout_ms! }
191
+ ).first
182
192
  if doc
183
193
  File::Info.new(Options::Mapper.transform(doc, File::Info::MAPPINGS.invert))
184
194
  else
@@ -209,6 +219,10 @@ module Mongo
209
219
  else
210
220
  options
211
221
  end
222
+ if @timeout_holder.csot?
223
+ opts[:timeout_ms] = @timeout_holder.remaining_timeout_ms!
224
+ opts[:timeout_mode] = :cursor_lifetime
225
+ end
212
226
 
213
227
  fs.chunks_collection.find({ :files_id => file_id }, opts).sort(:n => 1)
214
228
  end