mongo 2.14.1 → 2.15.0.alpha

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 (230) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +4 -1
  4. data/Rakefile +8 -15
  5. data/lib/mongo/auth/aws/conversation.rb +1 -4
  6. data/lib/mongo/auth/base.rb +13 -7
  7. data/lib/mongo/auth/conversation_base.rb +32 -0
  8. data/lib/mongo/auth/cr/conversation.rb +6 -29
  9. data/lib/mongo/auth/gssapi/conversation.rb +4 -15
  10. data/lib/mongo/auth/ldap/conversation.rb +3 -14
  11. data/lib/mongo/auth/sasl_conversation_base.rb +1 -13
  12. data/lib/mongo/auth/scram_conversation_base.rb +7 -34
  13. data/lib/mongo/auth/user/view.rb +16 -9
  14. data/lib/mongo/auth/x509/conversation.rb +4 -25
  15. data/lib/mongo/bulk_write.rb +21 -18
  16. data/lib/mongo/client.rb +82 -6
  17. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -2
  18. data/lib/mongo/cluster.rb +19 -2
  19. data/lib/mongo/collection/view/aggregation.rb +1 -1
  20. data/lib/mongo/collection/view/change_stream.rb +1 -1
  21. data/lib/mongo/collection/view/iterable.rb +7 -17
  22. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  23. data/lib/mongo/collection/view/readable.rb +42 -20
  24. data/lib/mongo/collection/view/writable.rb +14 -14
  25. data/lib/mongo/collection.rb +6 -6
  26. data/lib/mongo/cursor.rb +2 -12
  27. data/lib/mongo/database/view.rb +1 -1
  28. data/lib/mongo/database.rb +8 -3
  29. data/lib/mongo/error/bulk_write_error.rb +17 -3
  30. data/lib/mongo/error/internal_driver_error.rb +22 -0
  31. data/lib/mongo/error/operation_failure.rb +21 -2
  32. data/lib/mongo/error/parser.rb +65 -12
  33. data/lib/mongo/error/server_api_conflict.rb +23 -0
  34. data/lib/mongo/error/server_api_not_supported.rb +24 -0
  35. data/lib/mongo/error/unmet_dependency.rb +21 -0
  36. data/lib/mongo/error.rb +9 -1
  37. data/lib/mongo/index/view.rb +21 -11
  38. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +27 -16
  39. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +26 -15
  40. data/lib/mongo/monitoring.rb +13 -4
  41. data/lib/mongo/operation/collections_info/command.rb +2 -2
  42. data/lib/mongo/operation/collections_info.rb +18 -1
  43. data/lib/mongo/operation/context.rb +99 -0
  44. data/lib/mongo/operation/indexes.rb +15 -1
  45. data/lib/mongo/operation/insert/command.rb +2 -2
  46. data/lib/mongo/operation/insert/legacy.rb +2 -2
  47. data/lib/mongo/operation/insert/op_msg.rb +2 -2
  48. data/lib/mongo/operation/list_collections/result.rb +4 -1
  49. data/lib/mongo/operation/parallel_scan/command.rb +2 -1
  50. data/lib/mongo/operation/result.rb +2 -0
  51. data/lib/mongo/operation/shared/executable.rb +24 -14
  52. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  53. data/lib/mongo/operation/shared/op_msg_or_command.rb +1 -7
  54. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +1 -7
  55. data/lib/mongo/operation/shared/polymorphic_operation.rb +39 -0
  56. data/lib/mongo/operation/shared/read_preference_supported.rb +36 -38
  57. data/lib/mongo/operation/shared/response_handling.rb +23 -23
  58. data/lib/mongo/operation/shared/sessions_supported.rb +15 -5
  59. data/lib/mongo/operation/shared/write.rb +8 -18
  60. data/lib/mongo/operation.rb +2 -2
  61. data/lib/mongo/protocol/compressed.rb +51 -5
  62. data/lib/mongo/protocol/message.rb +20 -2
  63. data/lib/mongo/protocol/msg.rb +38 -13
  64. data/lib/mongo/protocol/query.rb +11 -11
  65. data/lib/mongo/query_cache.rb +30 -0
  66. data/lib/mongo/retryable.rb +1 -1
  67. data/lib/mongo/server/app_metadata.rb +52 -18
  68. data/lib/mongo/server/connection.rb +5 -0
  69. data/lib/mongo/server/connection_base.rb +13 -10
  70. data/lib/mongo/server/connection_pool.rb +6 -2
  71. data/lib/mongo/server/description/features.rb +9 -8
  72. data/lib/mongo/server/description.rb +4 -0
  73. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  74. data/lib/mongo/server/monitor/connection.rb +9 -10
  75. data/lib/mongo/server/monitor.rb +20 -1
  76. data/lib/mongo/server/pending_connection.rb +24 -6
  77. data/lib/mongo/server/push_monitor.rb +11 -1
  78. data/lib/mongo/server.rb +7 -1
  79. data/lib/mongo/server_selector/secondary_preferred.rb +7 -2
  80. data/lib/mongo/session/session_pool.rb +4 -2
  81. data/lib/mongo/session.rb +2 -2
  82. data/lib/mongo/socket/ssl.rb +8 -0
  83. data/lib/mongo/socket.rb +29 -4
  84. data/lib/mongo/uri/options_mapper.rb +38 -0
  85. data/lib/mongo/utils.rb +15 -0
  86. data/lib/mongo/version.rb +1 -1
  87. data/lib/mongo.rb +23 -0
  88. data/spec/README.md +24 -1
  89. data/spec/integration/auth_spec.rb +25 -15
  90. data/spec/integration/bulk_write_error_message_spec.rb +41 -0
  91. data/spec/integration/change_stream_spec.rb +4 -4
  92. data/spec/integration/command_monitoring_spec.rb +2 -2
  93. data/spec/integration/connection_spec.rb +2 -0
  94. data/spec/integration/docs_examples_spec.rb +8 -1
  95. data/spec/integration/fork_reconnect_spec.rb +4 -1
  96. data/spec/integration/ocsp_verifier_spec.rb +13 -7
  97. data/spec/integration/operation_failure_code_spec.rb +1 -1
  98. data/spec/integration/operation_failure_message_spec.rb +90 -0
  99. data/spec/integration/query_cache_spec.rb +0 -45
  100. data/spec/integration/reconnect_spec.rb +1 -1
  101. data/spec/integration/snappy_compression_spec.rb +25 -0
  102. data/spec/integration/srv_monitoring_spec.rb +1 -1
  103. data/spec/integration/transactions_examples_spec.rb +6 -0
  104. data/spec/integration/zlib_compression_spec.rb +1 -1
  105. data/spec/integration/zstd_compression_spec.rb +26 -0
  106. data/spec/lite_spec_helper.rb +7 -1
  107. data/spec/mongo/address_spec.rb +15 -11
  108. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  109. data/spec/mongo/auth/ldap_spec.rb +5 -1
  110. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -1
  111. data/spec/mongo/auth/scram_spec.rb +1 -1
  112. data/spec/mongo/auth/x509/conversation_spec.rb +3 -3
  113. data/spec/mongo/client_construction_spec.rb +207 -33
  114. data/spec/mongo/client_spec.rb +17 -0
  115. data/spec/mongo/cluster_spec.rb +1 -0
  116. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  117. data/spec/mongo/collection/view/readable_spec.rb +33 -19
  118. data/spec/mongo/collection_crud_spec.rb +4357 -0
  119. data/spec/mongo/collection_ddl_spec.rb +534 -0
  120. data/spec/mongo/collection_spec.rb +5 -4859
  121. data/spec/mongo/database_spec.rb +66 -4
  122. data/spec/mongo/error/bulk_write_error_spec.rb +3 -3
  123. data/spec/mongo/error/parser_spec.rb +37 -6
  124. data/spec/mongo/index/view_spec.rb +4 -0
  125. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +1 -1
  126. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +1 -1
  127. data/spec/mongo/operation/aggregate_spec.rb +2 -1
  128. data/spec/mongo/operation/collections_info_spec.rb +4 -1
  129. data/spec/mongo/operation/command_spec.rb +6 -3
  130. data/spec/mongo/operation/create_index_spec.rb +6 -3
  131. data/spec/mongo/operation/create_user_spec.rb +6 -3
  132. data/spec/mongo/operation/delete/bulk_spec.rb +9 -6
  133. data/spec/mongo/operation/delete_spec.rb +11 -7
  134. data/spec/mongo/operation/drop_index_spec.rb +6 -2
  135. data/spec/mongo/operation/find/legacy_spec.rb +3 -1
  136. data/spec/mongo/operation/get_more_spec.rb +3 -1
  137. data/spec/mongo/operation/indexes_spec.rb +5 -1
  138. data/spec/mongo/operation/insert/bulk_spec.rb +10 -7
  139. data/spec/mongo/operation/insert_spec.rb +15 -12
  140. data/spec/mongo/operation/map_reduce_spec.rb +5 -2
  141. data/spec/mongo/operation/read_preference_legacy_spec.rb +19 -9
  142. data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
  143. data/spec/mongo/operation/remove_user_spec.rb +6 -3
  144. data/spec/mongo/operation/result_spec.rb +1 -1
  145. data/spec/mongo/operation/update/bulk_spec.rb +9 -6
  146. data/spec/mongo/operation/update_spec.rb +10 -7
  147. data/spec/mongo/operation/update_user_spec.rb +4 -1
  148. data/spec/mongo/protocol/compressed_spec.rb +26 -12
  149. data/spec/mongo/query_cache_middleware_spec.rb +55 -0
  150. data/spec/mongo/retryable_spec.rb +3 -2
  151. data/spec/mongo/server/app_metadata_shared.rb +7 -33
  152. data/spec/mongo/server/app_metadata_spec.rb +2 -0
  153. data/spec/mongo/server/connection_pool/populator_spec.rb +3 -1
  154. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  155. data/spec/mongo/server/connection_spec.rb +24 -17
  156. data/spec/mongo/server/monitor/connection_spec.rb +17 -7
  157. data/spec/mongo/server/monitor_spec.rb +9 -1
  158. data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
  159. data/spec/mongo/server_spec.rb +15 -2
  160. data/spec/mongo/socket/ssl_spec.rb +40 -0
  161. data/spec/mongo/socket_spec.rb +2 -2
  162. data/spec/mongo/tls_context_hooks_spec.rb +37 -0
  163. data/spec/runners/connection_string.rb +0 -4
  164. data/spec/runners/crud/requirement.rb +40 -3
  165. data/spec/runners/crud/verifier.rb +8 -0
  166. data/spec/runners/transactions/operation.rb +1 -1
  167. data/spec/runners/transactions/test.rb +1 -0
  168. data/spec/runners/unified/assertions.rb +249 -0
  169. data/spec/runners/unified/change_stream_operations.rb +26 -0
  170. data/spec/runners/unified/crud_operations.rb +199 -0
  171. data/spec/runners/unified/ddl_operations.rb +96 -0
  172. data/spec/runners/unified/entity_map.rb +39 -0
  173. data/spec/runners/unified/error.rb +25 -0
  174. data/spec/runners/unified/event_subscriber.rb +91 -0
  175. data/spec/runners/unified/exceptions.rb +21 -0
  176. data/spec/runners/unified/grid_fs_operations.rb +55 -0
  177. data/spec/runners/unified/support_operations.rb +250 -0
  178. data/spec/runners/unified/test.rb +393 -0
  179. data/spec/runners/unified/test_group.rb +28 -0
  180. data/spec/runners/unified/using_hash.rb +31 -0
  181. data/spec/runners/unified.rb +96 -0
  182. data/spec/shared/lib/mrss/cluster_config.rb +0 -3
  183. data/spec/shared/lib/mrss/docker_runner.rb +0 -3
  184. data/spec/shared/lib/mrss/lite_constraints.rb +0 -16
  185. data/spec/shared/lib/mrss/server_version_registry.rb +0 -3
  186. data/spec/shared/lib/mrss/spec_organizer.rb +0 -3
  187. data/spec/shared/shlib/server.sh +1 -1
  188. data/spec/spec_helper.rb +4 -1
  189. data/spec/spec_tests/crud_unified_spec.rb +10 -0
  190. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  191. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +267 -0
  192. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-4.9.yml +60 -0
  193. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount.yml → estimatedDocumentCount-pre4.9.yml} +2 -0
  194. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors-4.9.yml +146 -0
  195. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors.yml → estimatedDocumentCount-serverErrors-pre4.9.yml} +2 -0
  196. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +1 -1
  197. data/spec/spec_tests/data/unified/valid-fail/operation-failure.yml +31 -0
  198. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +220 -0
  199. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +102 -0
  200. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +184 -0
  201. data/spec/spec_tests/data/unified/valid-pass/poc-gridfs.yml +155 -0
  202. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +193 -0
  203. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +210 -0
  204. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +215 -0
  205. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +235 -0
  206. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +169 -0
  207. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +170 -0
  208. data/spec/spec_tests/data/uri_options/compression-options.yml +1 -1
  209. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +416 -0
  210. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +409 -0
  211. data/spec/spec_tests/data/versioned_api/runcommand-helper-no-api-version-declared.yml +67 -0
  212. data/spec/spec_tests/data/versioned_api/test-commands-deprecation-errors.yml +47 -0
  213. data/spec/spec_tests/data/versioned_api/test-commands-strict-mode.yml +44 -0
  214. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +180 -0
  215. data/spec/spec_tests/unified_spec.rb +15 -0
  216. data/spec/spec_tests/uri_options_spec.rb +16 -0
  217. data/spec/spec_tests/versioned_api_spec.rb +10 -0
  218. data/spec/support/client_registry.rb +4 -8
  219. data/spec/support/client_registry_macros.rb +4 -4
  220. data/spec/support/common_shortcuts.rb +15 -1
  221. data/spec/support/shared/session.rb +2 -2
  222. data/spec/support/spec_config.rb +42 -11
  223. data/spec/support/utils.rb +64 -3
  224. data.tar.gz.sig +0 -0
  225. metadata +1005 -915
  226. metadata.gz.sig +0 -0
  227. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +0 -58
  228. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +0 -47
  229. data/spec/integration/secondary_reads_spec.rb +0 -102
  230. data/spec/support/cluster_config.rb +0 -207
@@ -15,9 +15,19 @@
15
15
  module Mongo
16
16
  class Error
17
17
 
18
- # Exception raised if there are write errors upon executing the bulk
18
+ # Exception raised if there are write errors upon executing a bulk
19
19
  # operation.
20
20
  #
21
+ # Unlike OperationFailure, BulkWriteError does not currently expose
22
+ # individual error components (such as the error code). The result document
23
+ # (which can be obtained using the +result+ attribute) provides detailed
24
+ # error information and can be examined by the application if desired.
25
+ #
26
+ # @note A bulk operation that resulted in a BulkWriteError may have
27
+ # written some of the documents to the database. If the bulk write
28
+ # was unordered, writes may have also continued past the write that
29
+ # produced a BulkWriteError.
30
+ #
21
31
  # @since 2.0.0
22
32
  class BulkWriteError < Error
23
33
 
@@ -47,11 +57,15 @@ module Mongo
47
57
  return nil unless errors
48
58
 
49
59
  fragment = errors.first(10).map do |error|
50
- "#{error['errmsg']} (#{error['code']})"
51
- end.join(', ')
60
+ "[#{error['code']}]: #{error['errmsg']}"
61
+ end.join('; ')
52
62
 
53
63
  fragment += '...' if errors.length > 10
54
64
 
65
+ if errors.length > 1
66
+ fragment = "Multiple errors: #{fragment}"
67
+ end
68
+
55
69
  fragment
56
70
  end
57
71
  end
@@ -0,0 +1,22 @@
1
+ # Copyright (C) 2021 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Error
17
+
18
+ # Raised when the driver detects an internal implementation problem.
19
+ class InternalDriverError < Error
20
+ end
21
+ end
22
+ end
@@ -89,6 +89,12 @@ module Mongo
89
89
  # @since 2.6.0
90
90
  attr_reader :code_name
91
91
 
92
+ # @return [ String ] The server-returned error message
93
+ # parsed from the response.
94
+ #
95
+ # @api experimental
96
+ attr_reader :server_message
97
+
92
98
  # Whether the error is a retryable error according to the legacy
93
99
  # read retry logic.
94
100
  #
@@ -215,6 +221,11 @@ module Mongo
215
221
  # @since 2.10.0
216
222
  attr_reader :write_concern_error_code_name
217
223
 
224
+ # @return [ BSON::Document | nil ] The server-returned error document.
225
+ #
226
+ # @api experimental
227
+ attr_reader :document
228
+
218
229
  # Create the operation failure.
219
230
  #
220
231
  # @example Create the error object
@@ -229,6 +240,10 @@ module Mongo
229
240
  #
230
241
  # @option options [ Integer ] :code Error code.
231
242
  # @option options [ String ] :code_name Error code name.
243
+ # @option options [ BSON::Document ] :document The server-returned
244
+ # error document.
245
+ # @option options [ String ] server_message The server-returned
246
+ # error message parsed from the response.
232
247
  # @option options [ Hash ] :write_concern_error_document The
233
248
  # server-supplied write concern error document, if any.
234
249
  # @option options [ Integer ] :write_concern_error_code Error code for
@@ -253,6 +268,8 @@ module Mongo
253
268
  @write_concern_error_labels = options[:write_concern_error_labels] || []
254
269
  @labels = options[:labels] || []
255
270
  @wtimeout = !!options[:wtimeout]
271
+ @document = options[:document]
272
+ @server_message = options[:server_message]
256
273
  end
257
274
 
258
275
  # Whether the error is a write concern timeout.
@@ -281,8 +298,10 @@ module Mongo
281
298
  #
282
299
  # @since 2.10.0
283
300
  def unsupported_retryable_write?
284
- # code 20 is IllegalOperation
285
- code == 20 && message.start_with?("Transaction numbers")
301
+ # code 20 is IllegalOperation.
302
+ # Note that the document is expected to be a BSON::Document, thus
303
+ # either having string keys or providing indifferent access.
304
+ code == 20 && server_message&.start_with?("Transaction numbers") || false
286
305
  end
287
306
  end
288
307
  end
@@ -42,28 +42,53 @@ module Mongo
42
42
  # Class for parsing the various forms that errors can come in from MongoDB
43
43
  # command responses.
44
44
  #
45
+ # The errors can be reported by the server in a number of ways:
46
+ # - {ok:0} response indicates failure. In newer servers, code, codeName
47
+ # and errmsg fields should be set. In older servers some may not be set.
48
+ # - {ok:1} response with a write concern error (writeConcernError top-level
49
+ # field). This indicates that the node responding successfully executed
50
+ # the request, but not enough other nodes successfully executed the
51
+ # request to satisfy the write concern.
52
+ # - {ok:1} response with writeErrors top-level field. This can be obtained
53
+ # in a bulk write but also in a non-bulk write. In a non-bulk write
54
+ # there should be exactly one error in the writeErrors list.
55
+ # The case of multiple errors is handled by BulkWrite::Result.
56
+ # - {ok:1} response with writeConcernErrors top-level field. This can
57
+ # only be obtained in a bulk write and is handled by BulkWrite::Result,
58
+ # not by this class.
59
+ #
60
+ # Note that writeErrors do not have codeName fields - they just provide
61
+ # codes and messages. writeConcernErrors may similarly not provide code
62
+ # names.
63
+ #
45
64
  # @since 2.0.0
65
+ # @api private
46
66
  class Parser
47
67
  include SdamErrorDetection
48
68
 
49
- # @return [ BSON::Document ] document The returned document.
69
+ # @return [ BSON::Document ] The returned document.
50
70
  attr_reader :document
51
71
 
52
- # @return [ String ] message The error message parsed from the document.
72
+ # @return [ String ] The full error message to be used in the
73
+ # raised exception.
53
74
  attr_reader :message
54
75
 
55
- # @return [ Array<Protocol::Message> ] replies The message replies.
76
+ # @return [ String ] The server-returned error message
77
+ # parsed from the response.
78
+ attr_reader :server_message
79
+
80
+ # @return [ Array<Protocol::Message> ] The message replies.
56
81
  attr_reader :replies
57
82
 
58
- # @return [ Integer ] code The error code parsed from the document.
83
+ # @return [ Integer ] The error code parsed from the document.
59
84
  # @since 2.6.0
60
85
  attr_reader :code
61
86
 
62
- # @return [ String ] code_name The error code name parsed from the document.
87
+ # @return [ String ] The error code name parsed from the document.
63
88
  # @since 2.6.0
64
89
  attr_reader :code_name
65
90
 
66
- # @return [ Array<String> ] labels The set of labels associated with the error.
91
+ # @return [ Array<String> ] The set of labels associated with the error.
67
92
  # @since 2.7.0
68
93
  attr_reader :labels
69
94
 
@@ -145,33 +170,61 @@ module Mongo
145
170
  write_concern_error_document && write_concern_error_document['errorLabels']
146
171
  end
147
172
 
173
+ class << self
174
+ def build_message(code: nil, code_name: nil, message: nil)
175
+ if code_name && code
176
+ "[#{code}:#{code_name}]: #{message}"
177
+ elsif code_name
178
+ # This surely should never happen, if there's a code name
179
+ # there ought to also be the code provided.
180
+ # Handle this case for completeness.
181
+ "[#{code_name}]: #{message}"
182
+ elsif code
183
+ "[#{code}]: #{message}"
184
+ else
185
+ message
186
+ end
187
+ end
188
+ end
189
+
148
190
  private
149
191
 
150
192
  def parse!
193
+ if document['ok'] != 1 && document['writeErrors']
194
+ raise ArgumentError, "writeErrors should only be given in successful responses"
195
+ end
196
+
151
197
  @message = ""
152
- parse_single(@message, ERR)
153
- parse_single(@message, ERROR)
154
- parse_single(@message, ERRMSG)
198
+ parse_single(@message, '$err')
199
+ parse_single(@message, 'err')
200
+ parse_single(@message, 'errmsg')
155
201
  parse_multiple(@message, 'writeErrors')
156
202
  if write_concern_error_document
157
- parse_single(@message, ERRMSG, write_concern_error_document)
203
+ parse_single(@message, 'errmsg', write_concern_error_document)
158
204
  end
159
205
  parse_flag(@message)
160
206
  parse_code
161
207
  parse_labels
162
208
  parse_wtimeout
209
+
210
+ @server_message = @message
211
+ @message = self.class.build_message(
212
+ code: code,
213
+ code_name: code_name,
214
+ message: @message,
215
+ )
163
216
  end
164
217
 
165
218
  def parse_single(message, key, doc = document)
166
219
  if error = doc[key]
167
- append(message ,"#{error} (#{doc[CODE]})")
220
+ append(message, error)
168
221
  end
169
222
  end
170
223
 
171
224
  def parse_multiple(message, key)
172
225
  if errors = document[key]
173
226
  errors.each do |error|
174
- parse_single(message, ERRMSG, error)
227
+ parse_single(message, 'errmsg', error)
175
228
  end
176
229
  end
177
230
  end
@@ -0,0 +1,23 @@
1
+ # Copyright (C) 2021 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Error
17
+
18
+ # Exception raised when a Client has :server_api configured and an
19
+ # operation attempts to specify any of server API version parameters.
20
+ class ServerApiConflict < Error
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # Copyright (C) 2021 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Error
17
+
18
+ # Exception raised when a Client has :server_api configured and an
19
+ # operation is executed against a pre-3.6 MongoDB server using a legacy
20
+ # wire protocol message that does not permit sending API parameters.
21
+ class ServerApiNotSupported < Error
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2020 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Error
17
+
18
+ # Raised if an optional dependency of the driver is not met.
19
+ class UnmetDependency < Error; end
20
+ end
21
+ end
data/lib/mongo/error.rb CHANGED
@@ -29,16 +29,19 @@ module Mongo
29
29
  # An error field, MongoDB < 2.6
30
30
  #
31
31
  # @since 2.0.0
32
+ # @deprecated
32
33
  ERR = '$err'.freeze
33
34
 
34
35
  # An error field, MongoDB < 2.4
35
36
  #
36
37
  # @since 2.0.0
38
+ # @deprecated
37
39
  ERROR = 'err'.freeze
38
40
 
39
41
  # The standard error message field, MongoDB 3.0+
40
42
  #
41
43
  # @since 2.0.0
44
+ # @deprecated
42
45
  ERRMSG = 'errmsg'.freeze
43
46
 
44
47
  # The constant for the writeErrors array.
@@ -174,7 +177,7 @@ require 'mongo/error/credential_check_error'
174
177
  require 'mongo/error/crypt_error'
175
178
  require 'mongo/error/extra_file_chunk'
176
179
  require 'mongo/error/file_not_found'
177
- require 'mongo/error/operation_failure'
180
+ require 'mongo/error/handshake_error'
178
181
  require 'mongo/error/invalid_address'
179
182
  require 'mongo/error/invalid_bulk_operation'
180
183
  require 'mongo/error/invalid_bulk_operation_type'
@@ -202,6 +205,7 @@ require 'mongo/error/invalid_update_document'
202
205
  require 'mongo/error/invalid_uri'
203
206
  require 'mongo/error/invalid_write_concern'
204
207
  require 'mongo/error/insufficient_iteration_count'
208
+ require 'mongo/error/internal_driver_error'
205
209
  require 'mongo/error/kms_error'
206
210
  require 'mongo/error/lint_error'
207
211
  require 'mongo/error/max_bson_size'
@@ -214,6 +218,7 @@ require 'mongo/error/no_server_available'
214
218
  require 'mongo/error/no_srv_records'
215
219
  require 'mongo/error/session_ended'
216
220
  require 'mongo/error/sessions_not_supported'
221
+ require 'mongo/error/operation_failure'
217
222
  require 'mongo/error/pool_closed_error'
218
223
  require 'mongo/error/raise_original_error'
219
224
  require 'mongo/error/server_certificate_revoked'
@@ -227,7 +232,10 @@ require 'mongo/error/missing_file_chunk'
227
232
  require 'mongo/error/missing_password'
228
233
  require 'mongo/error/missing_resume_token'
229
234
  require 'mongo/error/missing_scram_server_signature'
235
+ require 'mongo/error/server_api_conflict'
236
+ require 'mongo/error/server_api_not_supported'
230
237
  require 'mongo/error/unknown_payload_type'
238
+ require 'mongo/error/unmet_dependency'
231
239
  require 'mongo/error/unsupported_option'
232
240
  require 'mongo/error/unsupported_array_filters'
233
241
  require 'mongo/error/unsupported_collation'
@@ -127,6 +127,7 @@ module Mongo
127
127
  # data-bearing members of a replica set, including the primary, must
128
128
  # complete the index builds successfully before the primary marks
129
129
  # the indexes as ready.
130
+ # @option options [ Session ] :session The session to use for the operation.
130
131
  #
131
132
  # @note Note that the options listed may be subset of those available.
132
133
  # See the MongoDB documentation for a full list of supported options by server version.
@@ -137,7 +138,15 @@ module Mongo
137
138
  def create_one(keys, options = {})
138
139
  options = options.dup
139
140
 
140
- create_options = { commit_quorum: options.delete(:commit_quorum) }
141
+ create_options = {}
142
+ if session = @options[:session]
143
+ create_options[:session] = session
144
+ end
145
+ %i(commit_quorum session).each do |key|
146
+ if value = options.delete(key)
147
+ create_options[key] = value
148
+ end
149
+ end
141
150
  create_many({ key: keys }.merge(options), create_options)
142
151
  end
143
152
 
@@ -166,19 +175,20 @@ module Mongo
166
175
  # - commit_quorum: Specify how many data-bearing members of a replica set,
167
176
  # including the primary, must complete the index builds successfully
168
177
  # before the primary marks the indexes as ready.
178
+ # - session: The session to use.
169
179
  #
170
180
  # @return [ Result ] The result of the command.
171
181
  #
172
182
  # @since 2.0.0
173
183
  def create_many(*models)
174
- client.send(:with_session, @options) do |session|
175
- server = next_primary(nil, session)
184
+ models = models.flatten
185
+ options = {}
186
+ if models && !models.last.key?(:key)
187
+ options = models.pop
188
+ end
176
189
 
177
- models = models.flatten
178
- options = {}
179
- if models && !models.last.key?(:key)
180
- options = models.pop
181
- end
190
+ client.send(:with_session, @options.merge(options)) do |session|
191
+ server = next_primary(nil, session)
182
192
 
183
193
  # While server versions 3.4 and newer generally perform option
184
194
  # validation, there was a bug on server versions 4.2.0 - 4.2.5 where
@@ -208,7 +218,7 @@ module Mongo
208
218
 
209
219
  spec[:write_concern] = write_concern if description.features.collation_enabled?
210
220
 
211
- Operation::CreateIndex.new(spec).execute(server, client: client)
221
+ Operation::CreateIndex.new(spec).execute(server, context: Operation::Context.new(client: client, session: session))
212
222
  end
213
223
  end
214
224
 
@@ -286,7 +296,7 @@ module Mongo
286
296
  }
287
297
  server = next_primary(nil, session)
288
298
  spec[:write_concern] = write_concern if server.with_connection { |connection| connection.features }.collation_enabled?
289
- Operation::DropIndex.new(spec).execute(server, client: client)
299
+ Operation::DropIndex.new(spec).execute(server, context: Operation::Context.new(client: client, session: session))
290
300
  end
291
301
  end
292
302
 
@@ -322,7 +332,7 @@ module Mongo
322
332
  end
323
333
 
324
334
  def send_initial_query(server, session)
325
- initial_query_op(session).execute(server, client: client)
335
+ initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
326
336
  end
327
337
 
328
338
  def with_generated_names(models, server)
@@ -21,6 +21,29 @@ module Mongo
21
21
  # @since 2.7.0
22
22
  class ServerHeartbeatFailed < Mongo::Event::Base
23
23
 
24
+ # Create the event.
25
+ #
26
+ # @example Create the event.
27
+ # ServerHeartbeatSucceeded.new(address, duration)
28
+ #
29
+ # @param [ Address ] address The server address.
30
+ # @param [ Float ] round_trip_time Duration of ismaster call in seconds.
31
+ # @param [ true | false ] awaited Whether the heartbeat was awaited.
32
+ # @param [ Monitoring::Event::ServerHeartbeatStarted ] started_event
33
+ # The corresponding started event.
34
+ #
35
+ # @since 2.7.0
36
+ # @api private
37
+ def initialize(address, round_trip_time, error, awaited: false,
38
+ started_event:
39
+ )
40
+ @address = address
41
+ @round_trip_time = round_trip_time
42
+ @error = error
43
+ @awaited = !!awaited
44
+ @started_event = started_event
45
+ end
46
+
24
47
  # @return [ Address ] address The server address.
25
48
  attr_reader :address
26
49
 
@@ -41,23 +64,11 @@ module Mongo
41
64
  @awaited
42
65
  end
43
66
 
44
- # Create the event.
45
- #
46
- # @example Create the event.
47
- # ServerHeartbeatSucceeded.new(address, duration)
48
- #
49
- # @param [ Address ] address The server address.
50
- # @param [ Float ] round_trip_time Duration of ismaster call in seconds.
51
- # @param [ true | false ] awaited Whether the heartbeat was awaited.
67
+ # @return [ Monitoring::Event::ServerHeartbeatStarted ]
68
+ # The corresponding started event.
52
69
  #
53
- # @since 2.7.0
54
- # @api private
55
- def initialize(address, round_trip_time, error, awaited: false)
56
- @address = address
57
- @round_trip_time = round_trip_time
58
- @error = error
59
- @awaited = !!awaited
60
- end
70
+ # @api experimental
71
+ attr_reader :started_event
61
72
 
62
73
  # Returns a concise yet useful summary of the event.
63
74
  #
@@ -21,20 +21,6 @@ module Mongo
21
21
  # @since 2.7.0
22
22
  class ServerHeartbeatSucceeded < Mongo::Event::Base
23
23
 
24
- # @return [ Address ] address The server address.
25
- attr_reader :address
26
-
27
- # @return [ Float ] round_trip_time Duration of ismaster call in seconds.
28
- attr_reader :round_trip_time
29
-
30
- # Alias of round_trip_time.
31
- alias :duration :round_trip_time
32
-
33
- # @return [ true | false ] Whether the heartbeat was awaited.
34
- def awaited?
35
- @awaited
36
- end
37
-
38
24
  # Create the event.
39
25
  #
40
26
  # @example Create the event.
@@ -43,15 +29,40 @@ module Mongo
43
29
  # @param [ Address ] address The server address.
44
30
  # @param [ Float ] round_trip_time Duration of ismaster call in seconds.
45
31
  # @param [ true | false ] awaited Whether the heartbeat was awaited.
32
+ # @param [ Monitoring::Event::ServerHeartbeatStarted ] started_event
33
+ # The corresponding started event.
46
34
  #
47
35
  # @since 2.7.0
48
36
  # @api private
49
- def initialize(address, round_trip_time, awaited: false)
37
+ def initialize(address, round_trip_time, awaited: false,
38
+ started_event:
39
+ )
50
40
  @address = address
51
41
  @round_trip_time = round_trip_time
52
42
  @awaited = !!awaited
43
+ @started_event = started_event
53
44
  end
54
45
 
46
+ # @return [ Address ] address The server address.
47
+ attr_reader :address
48
+
49
+ # @return [ Float ] round_trip_time Duration of ismaster call in seconds.
50
+ attr_reader :round_trip_time
51
+
52
+ # Alias of round_trip_time.
53
+ alias :duration :round_trip_time
54
+
55
+ # @return [ true | false ] Whether the heartbeat was awaited.
56
+ def awaited?
57
+ @awaited
58
+ end
59
+
60
+ # @return [ Monitoring::Event::ServerHeartbeatStarted ]
61
+ # The corresponding started event.
62
+ #
63
+ # @api experimental
64
+ attr_reader :started_event
65
+
55
66
  # Returns a concise yet useful summary of the event.
56
67
  #
57
68
  # @return [ String ] String summary of the event.
@@ -307,9 +307,9 @@ module Mongo
307
307
  # @api private
308
308
  def publish_heartbeat(server, awaited: false)
309
309
  if monitoring?
310
- event = Event::ServerHeartbeatStarted.new(
310
+ started_event = Event::ServerHeartbeatStarted.new(
311
311
  server.address, awaited: awaited)
312
- started(SERVER_HEARTBEAT, event)
312
+ started(SERVER_HEARTBEAT, started_event)
313
313
  end
314
314
 
315
315
  # The duration we publish in heartbeat succeeded/failed events is
@@ -328,14 +328,23 @@ module Mongo
328
328
  rescue => exc
329
329
  if monitoring?
330
330
  event = Event::ServerHeartbeatFailed.new(
331
- server.address, Time.now-start_time, exc, awaited: awaited)
331
+ server.address,
332
+ Time.now-start_time,
333
+ exc,
334
+ awaited: awaited,
335
+ started_event: started_event,
336
+ )
332
337
  failed(SERVER_HEARTBEAT, event)
333
338
  end
334
339
  raise
335
340
  else
336
341
  if monitoring?
337
342
  event = Event::ServerHeartbeatSucceeded.new(
338
- server.address, Time.now-start_time, awaited: awaited)
343
+ server.address,
344
+ Time.now-start_time,
345
+ awaited: awaited,
346
+ started_event: started_event,
347
+ )
339
348
  succeeded(SERVER_HEARTBEAT, event)
340
349
  end
341
350
  result
@@ -27,9 +27,9 @@ module Mongo
27
27
 
28
28
  private
29
29
 
30
- def get_result(connection, client, options = {})
30
+ def get_result(connection, context, options = {})
31
31
  # This is a Mongo::Operation::CollectionsInfo::Result
32
- Result.new(*dispatch_message(connection, client), db_name)
32
+ Result.new(*dispatch_message(connection, context), db_name)
33
33
  end
34
34
 
35
35
  def selector(connection)
@@ -25,7 +25,24 @@ module Mongo
25
25
  # @since 2.0.0
26
26
  class CollectionsInfo
27
27
  include Specifiable
28
- include CollectionsInfoOrListCollections
28
+ include PolymorphicOperation
29
+ include PolymorphicLookup
30
+
31
+ private
32
+
33
+ def final_operation(connection)
34
+ op_class = if connection.features.list_collections_enabled?
35
+ if connection.features.op_msg_enabled?
36
+ ListCollections::OpMsg
37
+ else
38
+ ListCollections::Command
39
+ end
40
+ else
41
+ CollectionsInfo::Command
42
+ end
43
+
44
+ op_class.new(spec)
45
+ end
29
46
  end
30
47
  end
31
48
  end