mongo 2.9.2 → 2.10.0.rc0

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 (227) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +1 -0
  5. data/lib/mongo/auth/user/view.rb +4 -4
  6. data/lib/mongo/bulk_write.rb +14 -8
  7. data/lib/mongo/bulk_write/result.rb +1 -1
  8. data/lib/mongo/bulk_write/result_combiner.rb +2 -2
  9. data/lib/mongo/bulk_write/transformable.rb +17 -9
  10. data/lib/mongo/client.rb +107 -16
  11. data/lib/mongo/cluster.rb +47 -25
  12. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  13. data/lib/mongo/cluster_time.rb +139 -0
  14. data/lib/mongo/collection.rb +84 -25
  15. data/lib/mongo/collection/view.rb +7 -3
  16. data/lib/mongo/collection/view/aggregation.rb +4 -4
  17. data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
  18. data/lib/mongo/collection/view/builder/find_command.rb +4 -1
  19. data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
  20. data/lib/mongo/collection/view/change_stream.rb +54 -66
  21. data/lib/mongo/collection/view/iterable.rb +2 -2
  22. data/lib/mongo/collection/view/map_reduce.rb +6 -4
  23. data/lib/mongo/collection/view/readable.rb +36 -16
  24. data/lib/mongo/collection/view/writable.rb +68 -22
  25. data/lib/mongo/cursor.rb +87 -20
  26. data/lib/mongo/database.rb +47 -43
  27. data/lib/mongo/database/view.rb +54 -11
  28. data/lib/mongo/error.rb +13 -4
  29. data/lib/mongo/error/invalid_write_concern.rb +2 -2
  30. data/lib/mongo/error/operation_failure.rb +65 -11
  31. data/lib/mongo/error/parser.rb +41 -8
  32. data/lib/mongo/grid/fs_bucket.rb +26 -6
  33. data/lib/mongo/grid/stream/read.rb +9 -2
  34. data/lib/mongo/grid/stream/write.rb +21 -5
  35. data/lib/mongo/index/view.rb +3 -3
  36. data/lib/mongo/lint.rb +10 -3
  37. data/lib/mongo/operation.rb +2 -0
  38. data/lib/mongo/operation/aggregate/result.rb +19 -6
  39. data/lib/mongo/operation/collections_info.rb +1 -1
  40. data/lib/mongo/operation/get_more/result.rb +9 -0
  41. data/lib/mongo/operation/list_collections/command.rb +1 -3
  42. data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
  43. data/lib/mongo/operation/parallel_scan/command.rb +4 -1
  44. data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
  45. data/lib/mongo/operation/result.rb +27 -4
  46. data/lib/mongo/operation/shared/executable.rb +19 -5
  47. data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
  48. data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
  49. data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
  50. data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
  51. data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
  52. data/lib/mongo/operation/shared/specifiable.rb +40 -0
  53. data/lib/mongo/operation/shared/unpinnable.rb +39 -0
  54. data/lib/mongo/operation/shared/write.rb +1 -1
  55. data/lib/mongo/protocol/update.rb +6 -2
  56. data/lib/mongo/retryable.rb +79 -39
  57. data/lib/mongo/server/connection.rb +10 -3
  58. data/lib/mongo/server/description.rb +25 -1
  59. data/lib/mongo/server/monitor/connection.rb +1 -1
  60. data/lib/mongo/server_selector.rb +10 -0
  61. data/lib/mongo/server_selector/selectable.rb +172 -32
  62. data/lib/mongo/session.rb +654 -581
  63. data/lib/mongo/session/session_pool.rb +1 -1
  64. data/lib/mongo/socket.rb +7 -28
  65. data/lib/mongo/socket/ssl.rb +26 -1
  66. data/lib/mongo/socket/tcp.rb +3 -0
  67. data/lib/mongo/socket/unix.rb +3 -0
  68. data/lib/mongo/uri.rb +112 -265
  69. data/lib/mongo/uri/srv_protocol.rb +4 -1
  70. data/lib/mongo/version.rb +1 -1
  71. data/lib/mongo/write_concern.rb +10 -29
  72. data/lib/mongo/write_concern/acknowledged.rb +12 -0
  73. data/lib/mongo/write_concern/base.rb +17 -13
  74. data/lib/mongo/write_concern/unacknowledged.rb +12 -0
  75. data/spec/atlas/atlas_connectivity_spec.rb +7 -37
  76. data/spec/atlas/operations_spec.rb +25 -0
  77. data/spec/integration/change_stream_examples_spec.rb +45 -31
  78. data/spec/integration/change_stream_spec.rb +305 -5
  79. data/spec/integration/client_spec.rb +44 -0
  80. data/spec/integration/command_monitoring_spec.rb +1 -0
  81. data/spec/integration/command_spec.rb +7 -1
  82. data/spec/integration/mmapv1_spec.rb +28 -0
  83. data/spec/integration/mongos_pinning_spec.rb +34 -0
  84. data/spec/integration/operation_failure_code_spec.rb +2 -2
  85. data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
  86. data/spec/integration/read_preference_spec.rb +485 -0
  87. data/spec/integration/retryable_writes_spec.rb +8 -19
  88. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  89. data/spec/integration/sdam_events_spec.rb +2 -2
  90. data/spec/integration/server_description_spec.rb +14 -17
  91. data/spec/integration/server_selector_spec.rb +7 -3
  92. data/spec/integration/server_spec.rb +48 -0
  93. data/spec/integration/ssl_uri_options_spec.rb +1 -1
  94. data/spec/integration/step_down_spec.rb +10 -4
  95. data/spec/integration/transactions_examples_spec.rb +11 -10
  96. data/spec/lite_spec_helper.rb +19 -16
  97. data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
  98. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
  99. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
  100. data/spec/mongo/bulk_write_spec.rb +12 -2
  101. data/spec/mongo/client_construction_spec.rb +160 -8
  102. data/spec/mongo/client_spec.rb +5 -4
  103. data/spec/mongo/cluster_spec.rb +6 -6
  104. data/spec/mongo/cluster_time_spec.rb +148 -0
  105. data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
  106. data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
  107. data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
  108. data/spec/mongo/collection/view/readable_spec.rb +4 -4
  109. data/spec/mongo/collection_spec.rb +331 -14
  110. data/spec/mongo/cursor_spec.rb +117 -5
  111. data/spec/mongo/database_spec.rb +240 -8
  112. data/spec/mongo/error/operation_failure_spec.rb +47 -1
  113. data/spec/mongo/error/parser_spec.rb +160 -23
  114. data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
  115. data/spec/mongo/operation/result_spec.rb +27 -0
  116. data/spec/mongo/operation/update/bulk_spec.rb +1 -0
  117. data/spec/mongo/retryable_spec.rb +2 -0
  118. data/spec/mongo/server/app_metadata_spec.rb +2 -2
  119. data/spec/mongo/server/connection_spec.rb +13 -17
  120. data/spec/mongo/server/monitor/connection_spec.rb +13 -10
  121. data/spec/mongo/server_selector_spec.rb +34 -2
  122. data/spec/mongo/session/session_pool_spec.rb +14 -3
  123. data/spec/mongo/session_spec.rb +3 -3
  124. data/spec/mongo/session_transaction_spec.rb +4 -3
  125. data/spec/mongo/socket/ssl_spec.rb +19 -5
  126. data/spec/mongo/socket_spec.rb +1 -62
  127. data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
  128. data/spec/mongo/uri_option_parsing_spec.rb +94 -8
  129. data/spec/mongo/uri_spec.rb +23 -10
  130. data/spec/mongo/write_concern_spec.rb +56 -3
  131. data/spec/spec_tests/change_streams_spec.rb +2 -1
  132. data/spec/spec_tests/cmap_spec.rb +1 -1
  133. data/spec/spec_tests/crud_spec.rb +12 -2
  134. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
  135. data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
  136. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
  137. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
  138. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
  139. data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
  140. data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
  141. data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
  142. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
  143. data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
  144. data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
  145. data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
  146. data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
  147. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
  148. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
  149. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
  150. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
  151. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
  152. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
  153. data/spec/spec_tests/data/transactions/abort.yml +3 -0
  154. data/spec/spec_tests/data/transactions/bulk.yml +3 -8
  155. data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
  156. data/spec/spec_tests/data/transactions/commit.yml +3 -1
  157. data/spec/spec_tests/data/transactions/count.yml +3 -0
  158. data/spec/spec_tests/data/transactions/delete.yml +3 -0
  159. data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
  160. data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
  161. data/spec/spec_tests/data/transactions/errors.yml +3 -0
  162. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
  163. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
  164. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
  165. data/spec/spec_tests/data/transactions/insert.yml +3 -0
  166. data/spec/spec_tests/data/transactions/isolation.yml +3 -0
  167. data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
  168. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
  169. data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
  170. data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
  171. data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
  172. data/spec/spec_tests/data/transactions/reads.yml +3 -0
  173. data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
  174. data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
  175. data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
  176. data/spec/spec_tests/data/transactions/run-command.yml +3 -0
  177. data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
  178. data/spec/spec_tests/data/transactions/update.yml +3 -8
  179. data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
  180. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
  181. data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
  182. data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
  183. data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
  184. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
  185. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
  186. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
  187. data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
  188. data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
  189. data/spec/spec_tests/retryable_reads_spec.rb +5 -2
  190. data/spec/spec_tests/retryable_writes_spec.rb +5 -2
  191. data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
  192. data/spec/spec_tests/sdam_spec.rb +2 -2
  193. data/spec/spec_tests/transactions_api_spec.rb +1 -67
  194. data/spec/spec_tests/transactions_spec.rb +2 -66
  195. data/spec/support/authorization.rb +4 -0
  196. data/spec/support/change_streams.rb +30 -10
  197. data/spec/support/change_streams/operation.rb +27 -0
  198. data/spec/support/client_registry.rb +44 -25
  199. data/spec/support/cluster_config.rb +25 -14
  200. data/spec/support/cluster_tools.rb +32 -10
  201. data/spec/support/command_monitoring.rb +1 -1
  202. data/spec/support/common_shortcuts.rb +30 -0
  203. data/spec/support/connection_string.rb +8 -3
  204. data/spec/support/constraints.rb +34 -0
  205. data/spec/support/crud.rb +31 -16
  206. data/spec/support/crud/context.rb +23 -0
  207. data/spec/support/crud/operation.rb +311 -14
  208. data/spec/support/crud/spec.rb +2 -1
  209. data/spec/support/crud/test.rb +24 -27
  210. data/spec/support/crud/test_base.rb +22 -0
  211. data/spec/support/crud/verifier.rb +15 -1
  212. data/spec/support/event_subscriber.rb +12 -0
  213. data/spec/support/sdam_formatter_integration.rb +12 -6
  214. data/spec/support/shared/server_selector.rb +10 -0
  215. data/spec/support/shared/session.rb +13 -12
  216. data/spec/support/spec_config.rb +32 -22
  217. data/spec/support/spec_setup.rb +2 -2
  218. data/spec/support/transactions.rb +87 -0
  219. data/spec/support/transactions/context.rb +33 -0
  220. data/spec/support/transactions/operation.rb +99 -349
  221. data/spec/support/transactions/spec.rb +1 -3
  222. data/spec/support/transactions/test.rb +110 -49
  223. data/spec/support/utils.rb +74 -1
  224. metadata +52 -10
  225. metadata.gz.sig +0 -0
  226. data/spec/support/crud/read.rb +0 -265
  227. data/spec/support/crud/write.rb +0 -284
@@ -24,6 +24,8 @@ module Mongo
24
24
  include Retryable
25
25
 
26
26
  def_delegators :@database, :cluster, :read_preference, :client
27
+ # @api private
28
+ def_delegators :@database, :server_selector, :read_concern
27
29
  def_delegators :cluster, :next_primary
28
30
 
29
31
  # @return [ Integer ] batch_size The size of the batch of results
@@ -38,8 +40,8 @@ module Mongo
38
40
 
39
41
  # Get all the names of the non-system collections in the database.
40
42
  #
41
- # @example Get the collection names.
42
- # database.collection_names
43
+ # @note The set of returned collection names depends on the version of
44
+ # MongoDB server that fulfills the request.
43
45
  #
44
46
  # @param [ Hash ] options Options for the listCollections command.
45
47
  #
@@ -52,21 +54,27 @@ module Mongo
52
54
  def collection_names(options = {})
53
55
  @batch_size = options[:batch_size]
54
56
  session = client.send(:get_session, options)
55
- cursor = read_with_retry_cursor(session, ServerSelector.get(mode: :primary), self) do |server|
57
+ cursor = read_with_retry_cursor(session, ServerSelector.primary, self) do |server|
56
58
  send_initial_query(server, session, name_only: true)
57
59
  end
58
60
  cursor.map do |info|
59
61
  if cursor.server.features.list_collections_enabled?
60
- info[Database::NAME]
62
+ info['name']
61
63
  else
62
- (info[Database::NAME] &&
63
- info[Database::NAME].sub("#{@database.name}.", ''))
64
+ (info['name'] &&
65
+ info['name'].sub("#{@database.name}.", ''))
64
66
  end
67
+ end.reject do |name|
68
+ name.start_with?('system.') || name.include?('$')
65
69
  end
66
70
  end
67
71
 
68
72
  # Get info on all the collections in the database.
69
73
  #
74
+ # @note The set of collections returned, and the schema of the
75
+ # information hash per collection, depends on the MongoDB server
76
+ # version that fulfills the request.
77
+ #
70
78
  # @example Get info on each collection.
71
79
  # database.list_collections
72
80
  #
@@ -75,7 +83,7 @@ module Mongo
75
83
  # @since 2.0.5
76
84
  def list_collections
77
85
  session = client.send(:get_session)
78
- collections_info(session, ServerSelector.get(mode: :primary))
86
+ collections_info(session, ServerSelector.primary)
79
87
  end
80
88
 
81
89
  # Create the new database view.
@@ -93,18 +101,53 @@ module Mongo
93
101
  @collection = @database[Database::COMMAND]
94
102
  end
95
103
 
104
+ # @api private
105
+ attr_reader :database
106
+
107
+ # Execute an aggregation on the database view.
108
+ #
109
+ # @example Aggregate documents.
110
+ # view.aggregate([
111
+ # { "$listLocalSessions" => {} }
112
+ # ])
113
+ #
114
+ # @param [ Array<Hash> ] pipeline The aggregation pipeline.
115
+ # @param [ Hash ] options The aggregation options.
116
+ #
117
+ # @return [ Aggregation ] The aggregation object.
118
+ #
119
+ # @since 2.10.0
120
+ # @api private
121
+ def aggregate(pipeline, options = {})
122
+ Collection::View::Aggregation.new(self, pipeline, options)
123
+ end
124
+
96
125
  private
97
126
 
98
127
  def collections_info(session, server_selector, options = {}, &block)
128
+ description = nil
99
129
  cursor = read_with_retry_cursor(session, server_selector, self) do |server|
130
+ # TODO take description from the connection used to send the query
131
+ # once https://jira.mongodb.org/browse/RUBY-1601 is fixed.
132
+ description = server.description
100
133
  send_initial_query(server, session, options)
101
134
  end
102
- if block_given?
103
- cursor.each do |doc|
104
- yield doc
135
+ # On 3.0+ servers, we get just the collection names.
136
+ # On 2.6 server, we get collection names prefixed with the database
137
+ # name. We need to filter system collections out here because
138
+ # in the caller we don't know which server version executed the
139
+ # command and thus what the proper filtering logic should be
140
+ # (it is valid for collection names to have dots, thus filtering out
141
+ # collections named system.* here for 2.6 servers would actually
142
+ # filter out collections in the system database).
143
+ if description.server_version_gte?('3.0')
144
+ cursor.reject do |doc|
145
+ doc['name'].start_with?('system.') || doc['name'].include?('$')
105
146
  end
106
147
  else
107
- cursor.to_enum
148
+ docs = cursor.reject do |doc|
149
+ doc['name'].start_with?("#{database.name}.system") || doc['name'].include?('$')
150
+ end
108
151
  end
109
152
  end
110
153
 
@@ -41,16 +41,19 @@ module Mongo
41
41
  # The constant for the writeErrors array.
42
42
  #
43
43
  # @since 2.0.0
44
+ # @deprecated
44
45
  WRITE_ERRORS = 'writeErrors'.freeze
45
46
 
46
47
  # The constant for a write concern error.
47
48
  #
48
49
  # @since 2.0.0
50
+ # @deprecated
49
51
  WRITE_CONCERN_ERROR = 'writeConcernError'.freeze
50
52
 
51
53
  # The constant for write concern errors.
52
54
  #
53
55
  # @since 2.1.0
56
+ # @deprecated
54
57
  WRITE_CONCERN_ERRORS = 'writeConcernErrors'.freeze
55
58
 
56
59
  # Constant for an unknown error.
@@ -85,17 +88,19 @@ module Mongo
85
88
  # manually retried by the user.
86
89
  #
87
90
  # @since 2.6.0
91
+ # @deprecated
88
92
  UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL = 'UnknownTransactionCommitResult'.freeze
89
93
 
90
94
  # Error label describing errors that will likely not occur if a transaction is manually retried
91
95
  # from the start.
92
96
  #
93
97
  # @since 2.6.0
98
+ # @deprecated
94
99
  TRANSIENT_TRANSACTION_ERROR_LABEL = 'TransientTransactionError'.freeze
95
100
 
96
101
  def initialize(msg = nil)
97
- @labels ||= []
98
- super(msg)
102
+ super
103
+ @labels = []
99
104
  end
100
105
 
101
106
  # Does the error have the given label?
@@ -124,8 +129,12 @@ module Mongo
124
129
  @labels.dup
125
130
  end
126
131
 
127
- private
128
-
132
+ # Adds the specified label to the error instance, if the label is not
133
+ # already in the set of labels.
134
+ #
135
+ # @param [ String ] label The label to add.
136
+ #
137
+ # @api private
129
138
  def add_label(label)
130
139
  @labels << label unless label?(label)
131
140
  end
@@ -26,8 +26,8 @@ module Mongo
26
26
  # Mongo::Error::InvalidWriteConcern.new
27
27
  #
28
28
  # @since 2.2.0
29
- def initialize
30
- super('Invalid write concern options. If w is an Integer, it must be greater than or equal to 0. ' +
29
+ def initialize(msg = nil)
30
+ super(msg || 'Invalid write concern options. If w is an Integer, it must be greater than or equal to 0. ' +
31
31
  'If w is 0, it cannot be combined with a true value for fsync or j (journal).')
32
32
  end
33
33
  end
@@ -70,11 +70,13 @@ module Mongo
70
70
 
71
71
  def_delegators :@result, :operation_time
72
72
 
73
- # @return [ Integer ] code The error code parsed from the document.
73
+ # @return [ Integer ] The error code parsed from the document.
74
+ #
74
75
  # @since 2.6.0
75
76
  attr_reader :code
76
77
 
77
- # @return [ String ] code_name The error code name parsed from the document.
78
+ # @return [ String ] The error code name parsed from the document.
79
+ #
78
80
  # @since 2.6.0
79
81
  attr_reader :code_name
80
82
 
@@ -141,8 +143,9 @@ module Mongo
141
143
  # @since 2.6.0
142
144
  def change_stream_resumable?
143
145
  if @result && @result.is_a?(Mongo::Operation::GetMore::Result)
144
- change_stream_resumable_message? ||
145
- change_stream_resumable_code?
146
+ !change_stream_not_resumable_label? &&
147
+ (change_stream_resumable_message? ||
148
+ change_stream_resumable_code?)
146
149
  else
147
150
  false
148
151
  end
@@ -162,6 +165,39 @@ module Mongo
162
165
  end
163
166
  private :change_stream_resumable_code?
164
167
 
168
+ def change_stream_not_resumable_label?
169
+ if labels
170
+ labels.include? 'NonResumableChangeStreamError'
171
+ else
172
+ false
173
+ end
174
+ end
175
+ private :change_stream_not_resumable_label?
176
+
177
+ # @return [ true | false ] Whether the failure includes a write
178
+ # concern error. A failure may have a top level error and a write
179
+ # concern error or either one of the two.
180
+ #
181
+ # @since 2.10.0
182
+ # @api experimental
183
+ def write_concern_error?
184
+ @write_concern_error
185
+ end
186
+
187
+ # @return [ Integer | nil ] The error code for the write concern error,
188
+ # if a write concern error is present and has a code.
189
+ #
190
+ # @since 2.10.0
191
+ # @api experimental
192
+ attr_reader :write_concern_error_code
193
+
194
+ # @return [ String | nil ] The code name for the write concern error,
195
+ # if a write concern error is present and has a code name.
196
+ #
197
+ # @since 2.10.0
198
+ # @api experimental
199
+ attr_reader :write_concern_error_code_name
200
+
165
201
  # Create the operation failure.
166
202
  #
167
203
  # @example Create the error object
@@ -172,22 +208,31 @@ module Mongo
172
208
  #
173
209
  # @param [ String ] message The error message.
174
210
  # @param [ Operation::Result ] result The result object.
175
- # @param [ Hash ] options Additional parameters
211
+ # @param [ Hash ] options Additional parameters.
176
212
  #
177
- # @option options [ Integer ] :code Error code
178
- # @option options [ String ] :code_name Error code name
213
+ # @option options [ Integer ] :code Error code.
214
+ # @option options [ String ] :code_name Error code name.
215
+ # @option options [ true | false ] :write_concern_error Whether the
216
+ # write concern error is present.
217
+ # @option options [ Integer ] :write_concern_error_code Error code for
218
+ # write concern error, if any.
219
+ # @option options [ String ] :write_concern_error_code_name Error code
220
+ # name for write concern error, if any.
179
221
  # @option options [ Array<String> ] :labels The set of labels associated
180
- # with the error
181
- # @option options [ true | false ] :wtimeout Whether the error is a wtimeout
222
+ # with the error.
223
+ # @option options [ true | false ] :wtimeout Whether the error is a wtimeout.
182
224
  #
183
225
  # @since 2.5.0, options added in 2.6.0
184
226
  def initialize(message = nil, result = nil, options = {})
227
+ super(message)
185
228
  @result = result
186
229
  @code = options[:code]
187
230
  @code_name = options[:code_name]
188
- @labels = options[:labels]
231
+ @write_concern_error = !!options[:write_concern_error]
232
+ @write_concern_error_code = options[:write_concern_error_code]
233
+ @write_concern_error_code_name = options[:write_concern_error_code_name]
234
+ @labels = options[:labels] || []
189
235
  @wtimeout = !!options[:wtimeout]
190
- super(message)
191
236
  end
192
237
 
193
238
  # Whether the error is a write concern timeout.
@@ -198,6 +243,15 @@ module Mongo
198
243
  def wtimeout?
199
244
  @wtimeout
200
245
  end
246
+
247
+ # Whether the error is MaxTimeMSExpired.
248
+ #
249
+ # @return [ true | false ] Whether the error is MaxTimeMSExpired.
250
+ #
251
+ # @since 2.10.0
252
+ def max_time_ms_expired?
253
+ code == 50 # MaxTimeMSExpired
254
+ end
201
255
  end
202
256
  end
203
257
  end
@@ -102,16 +102,49 @@ module Mongo
102
102
  parse!
103
103
  end
104
104
 
105
+ # @return [ true | false ] Whether the document includes a write
106
+ # concern error. A failure may have a top level error and a write
107
+ # concern error or either one of the two.
108
+ #
109
+ # @since 2.10.0
110
+ # @api experimental
111
+ def write_concern_error?
112
+ !!write_concern_error_document
113
+ end
114
+
115
+ # @return [ Integer | nil ] The error code for the write concern error,
116
+ # if a write concern error is present and has a code.
117
+ #
118
+ # @since 2.10.0
119
+ # @api experimental
120
+ def write_concern_error_code
121
+ write_concern_error_document && write_concern_error_document['code']
122
+ end
123
+
124
+ # @return [ String | nil ] The code name for the write concern error,
125
+ # if a write concern error is present and has a code name.
126
+ #
127
+ # @since 2.10.0
128
+ # @api experimental
129
+ def write_concern_error_code_name
130
+ write_concern_error_document && write_concern_error_document['codeName']
131
+ end
132
+
105
133
  private
106
134
 
135
+ def write_concern_error_document
136
+ document['writeConcernError']
137
+ end
138
+
107
139
  def parse!
108
140
  @message = ""
109
141
  parse_single(@message, ERR)
110
142
  parse_single(@message, ERROR)
111
143
  parse_single(@message, ERRMSG)
112
- parse_multiple(@message, WRITE_ERRORS)
113
- parse_single(@message, ERRMSG,
114
- document[WRITE_CONCERN_ERROR]) if document[WRITE_CONCERN_ERROR]
144
+ parse_multiple(@message, 'writeErrors')
145
+ if write_concern_error_document
146
+ parse_single(@message, ERRMSG, write_concern_error_document)
147
+ end
115
148
  parse_flag(@message)
116
149
  parse_code
117
150
  parse_labels
@@ -160,7 +193,7 @@ module Mongo
160
193
  # In practice this should never be an issue as a write concern
161
194
  # can only fail after the operation succeeds on the primary.
162
195
  if @code.nil? && @code_name.nil?
163
- if subdoc = document[WRITE_CONCERN_ERROR]
196
+ if subdoc = write_concern_error_document
164
197
  @code = subdoc['code']
165
198
  @code_name = subdoc['codeName']
166
199
  end
@@ -169,7 +202,7 @@ module Mongo
169
202
  if @code.nil? && @code_name.nil?
170
203
  # If we have writeErrors, and all of their codes are the same,
171
204
  # use that code. Otherwise don't set the code
172
- if write_errors = document[WRITE_ERRORS]
205
+ if write_errors = document['writeErrors']
173
206
  codes = write_errors.map { |e| e['code'] }.compact
174
207
  if codes.uniq.length == 1
175
208
  @code = codes.first
@@ -185,9 +218,9 @@ module Mongo
185
218
  end
186
219
 
187
220
  def parse_wtimeout
188
- @wtimeout = document[WRITE_CONCERN_ERROR] &&
189
- document[WRITE_CONCERN_ERROR]['errInfo'] &&
190
- document[WRITE_CONCERN_ERROR]['errInfo']['wtimeout']
221
+ @wtimeout = write_concern_error_document &&
222
+ write_concern_error_document['errInfo'] &&
223
+ write_concern_error_document['errInfo']['wtimeout']
191
224
  end
192
225
  end
193
226
  end
@@ -145,14 +145,25 @@ module Mongo
145
145
  # collections.
146
146
  # @option options [ Integer ] :chunk_size Override the default chunk
147
147
  # size.
148
- # @option options [ String ] :write The write concern.
149
148
  # @option options [ String ] :read The read preference.
150
149
  # @option options [ Session ] :session The session to use.
150
+ # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
151
+ # option.
152
+ # @option options [ Hash ] :write_concern The write concern options.
153
+ # Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
151
154
  #
152
155
  # @since 2.0.0
153
156
  def initialize(database, options = {})
154
157
  @database = database
155
- @options = options
158
+ @options = options.dup
159
+ =begin WriteConcern object support
160
+ if @options[:write_concern].is_a?(WriteConcern::Base)
161
+ # Cache the instance so that we do not needlessly reconstruct it.
162
+ @write_concern = @options[:write_concern]
163
+ @options[:write_concern] = @write_concern.options
164
+ end
165
+ =end
166
+ @options.freeze
156
167
  @chunks_collection = database[chunks_name]
157
168
  @files_collection = database[files_name]
158
169
  end
@@ -347,13 +358,16 @@ module Mongo
347
358
  #
348
359
  # @option opts [ Object ] :file_id An optional unique file id. An ObjectId is generated otherwise.
349
360
  # @option opts [ Integer ] :chunk_size Override the default chunk size.
350
- # @option opts [ Hash ] :write The write concern.
351
361
  # @option opts [ Hash ] :metadata User data for the 'metadata' field of the files
352
362
  # collection document.
353
363
  # @option opts [ String ] :content_type The content type of the file.
354
364
  # Deprecated, please use the metadata document instead.
355
365
  # @option opts [ Array<String> ] :aliases A list of aliases.
356
366
  # Deprecated, please use the metadata document instead.
367
+ # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
368
+ # option.
369
+ # @option options [ Hash ] :write_concern The write concern options.
370
+ # Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
357
371
  #
358
372
  # @return [ Stream::Write ] The write stream.
359
373
  #
@@ -386,13 +400,16 @@ module Mongo
386
400
  #
387
401
  # @option opts [ Object ] :file_id An optional unique file id. An ObjectId is generated otherwise.
388
402
  # @option opts [ Integer ] :chunk_size Override the default chunk size.
389
- # @option opts [ Hash ] :write The write concern.
390
403
  # @option opts [ Hash ] :metadata User data for the 'metadata' field of the files
391
404
  # collection document.
392
405
  # @option opts [ String ] :content_type The content type of the file. Deprecated, please
393
406
  # use the metadata document instead.
394
407
  # @option opts [ Array<String> ] :aliases A list of aliases. Deprecated, please use the
395
408
  # metadata document instead.
409
+ # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
410
+ # option.
411
+ # @option options [ Hash ] :write_concern The write concern options.
412
+ # Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
396
413
  #
397
414
  # @return [ BSON::ObjectId ] The ObjectId file id.
398
415
  #
@@ -432,8 +449,11 @@ module Mongo
432
449
  #
433
450
  # @since 2.1.0
434
451
  def write_concern
435
- @write_concern ||= @options[:write] ? WriteConcern.get(@options[:write]) :
436
- database.write_concern
452
+ @write_concern ||= if wco = @options[:write_concern] || @options[:write]
453
+ WriteConcern.get(wco)
454
+ else
455
+ database.write_concern
456
+ end
437
457
  end
438
458
 
439
459
  private