mongo 2.9.2 → 2.10.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -182,8 +182,15 @@ module Mongo
182
182
  end
183
183
 
184
184
  def view
185
- @view ||= (opts = options.merge(read: read_preference) if read_preference
186
- fs.chunks_collection.find({ :files_id => file_id }, opts || options).sort(:n => 1))
185
+ @view ||= begin
186
+ opts = if read_preference
187
+ options.merge(read: read_preference)
188
+ else
189
+ options
190
+ end
191
+
192
+ fs.chunks_collection.find({ :files_id => file_id }, opts).sort(:n => 1)
193
+ end
187
194
  end
188
195
 
189
196
  def validate!(index, num_chunks, chunk, length_read)
@@ -50,14 +50,18 @@ module Mongo
50
50
  # @param [ FSBucket ] fs The GridFS bucket object.
51
51
  # @param [ Hash ] options The write stream options.
52
52
  #
53
- # @option opts [ Object ] :file_id The file id. An ObjectId is generated otherwise.
53
+ # @option options [ Object ] :file_id The file id. An ObjectId
54
+ # is generated if the file id is not provided.
54
55
  # @option opts [ Integer ] :chunk_size Override the default chunk size.
55
- # @option opts [ Hash ] :write The write concern.
56
56
  # @option opts [ Hash ] :metadata User data for the 'metadata' field of the files collection document.
57
57
  # @option opts [ String ] :content_type The content type of the file.
58
58
  # Deprecated, please use the metadata document instead.
59
59
  # @option opts [ Array<String> ] :aliases A list of aliases.
60
60
  # Deprecated, please use the metadata document instead.
61
+ # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
62
+ # option.
63
+ # @option options [ Hash ] :write_concern The write concern options.
64
+ # Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
61
65
  #
62
66
  # @since 2.1.0
63
67
  def initialize(fs, options)
@@ -65,7 +69,15 @@ module Mongo
65
69
  @length = 0
66
70
  @n = 0
67
71
  @file_id = options[:file_id] || BSON::ObjectId.new
68
- @options = options
72
+ @options = options.dup
73
+ =begin WriteConcern object support
74
+ if @options[:write_concern].is_a?(WriteConcern::Base)
75
+ # Cache the instance so that we do not needlessly reconstruct it.
76
+ @write_concern = @options[:write_concern]
77
+ @options[:write_concern] = @write_concern.options
78
+ end
79
+ =end
80
+ @options.freeze
69
81
  @filename = @options[:filename]
70
82
  @open = true
71
83
  end
@@ -117,8 +129,11 @@ module Mongo
117
129
  #
118
130
  # @since 2.1.0
119
131
  def write_concern
120
- @write_concern ||= @options[:write] ? WriteConcern.get(@options[:write]) :
132
+ @write_concern ||= if wco = @options[:write_concern] || @options[:write]
133
+ WriteConcern.get(wco)
134
+ else
121
135
  fs.write_concern
136
+ end
122
137
  end
123
138
 
124
139
  # Is the stream closed.
@@ -158,7 +173,8 @@ module Mongo
158
173
 
159
174
  def with_write_concern(collection)
160
175
  if write_concern.nil? || (collection.write_concern &&
161
- collection.write_concern.options == write_concern.options)
176
+ collection.write_concern.options == write_concern.options)
177
+ then
162
178
  collection
163
179
  else
164
180
  collection.with(write: write_concern.options)
@@ -149,8 +149,8 @@ module Mongo
149
149
  #
150
150
  # @since 2.0.0
151
151
  def create_many(*models)
152
- server = next_primary
153
152
  client.send(:with_session, @options) do |session|
153
+ server = next_primary(nil, session)
154
154
  spec = {
155
155
  indexes: normalize_models(models.flatten, server),
156
156
  db_name: database.name,
@@ -192,7 +192,7 @@ module Mongo
192
192
  # @since 2.0.0
193
193
  def each(&block)
194
194
  session = client.send(:get_session, @options)
195
- cursor = read_with_retry_cursor(session, ServerSelector.get(mode: :primary), self) do |server|
195
+ cursor = read_with_retry_cursor(session, ServerSelector.primary, self) do |server|
196
196
  send_initial_query(server, session)
197
197
  end
198
198
  if block_given?
@@ -234,7 +234,7 @@ module Mongo
234
234
  index_name: name,
235
235
  session: session
236
236
  }
237
- server = next_primary
237
+ server = next_primary(nil, session)
238
238
  spec[:write_concern] = write_concern if server.features.collation_enabled?
239
239
  Operation::DropIndex.new(spec).execute(server)
240
240
  end
@@ -67,12 +67,19 @@ module Mongo
67
67
  end
68
68
  return if read_concern.empty?
69
69
  keys = read_concern.keys
70
- if keys != [:level]
70
+ if read_concern.is_a?(BSON::Document)
71
+ # Permits indifferent access
72
+ allowed_keys = ['level']
73
+ else
74
+ # Does not permit indifferent access
75
+ allowed_keys = [:level]
76
+ end
77
+ if keys != allowed_keys
71
78
  raise Error::LintError, "Read concern has invalid keys: #{keys.inspect}"
72
79
  end
73
80
  level = read_concern[:level]
74
- return if [:local, :majority, :snapshot].include?(level)
75
- raise Error::LintError, "Read concern level is invalid: #{level.inspect}"
81
+ return if [:local, :available, :majority, :linearizable, :snapshot].include?(level)
82
+ raise Error::LintError, "Read concern level is invalid: value must be a symbol: #{level.inspect}"
76
83
  end
77
84
  module_function :validate_read_concern_option
78
85
 
@@ -13,6 +13,7 @@ require 'mongo/operation/shared/sessions_supported'
13
13
  require 'mongo/operation/shared/causal_consistency_supported'
14
14
  require 'mongo/operation/shared/write'
15
15
  require 'mongo/operation/shared/idable'
16
+ require 'mongo/operation/shared/unpinnable'
16
17
  require 'mongo/operation/shared/specifiable'
17
18
  require 'mongo/operation/shared/object_id_generator'
18
19
  require 'mongo/operation/shared/op_msg_or_command'
@@ -93,6 +94,7 @@ module Mongo
93
94
  # The cluster time field constant.
94
95
  #
95
96
  # @since 2.5.0
97
+ # @deprecated
96
98
  CLUSTER_TIME = '$clusterTime'.freeze
97
99
  end
98
100
  end
@@ -52,10 +52,19 @@ module Mongo
52
52
  cursor_document ? cursor_document[CURSOR_ID] : 0
53
53
  end
54
54
 
55
+ # Get the post batch resume token for the result
56
+ #
57
+ # @return [ BSON::Document | nil ] The post batch resume token
58
+ #
59
+ # @api private
60
+ def post_batch_resume_token
61
+ cursor_document ? cursor_document['postBatchResumeToken'] : nil
62
+ end
63
+
55
64
  # Get the documents for the aggregation result. This is either the
56
- # first document's 'result' field, or if a cursor option was selected
57
- # it is the 'firstBatch' field in the 'cursor' field of the first
58
- # document returned.
65
+ # first document's 'result' field, or if a cursor option was selected,
66
+ # it is the 'firstBatch' field in the 'cursor' field of the first
67
+ # document returned. Otherwise, it is an explain document.
59
68
  #
60
69
  # @example Get the documents.
61
70
  # result.documents
@@ -64,14 +73,18 @@ module Mongo
64
73
  #
65
74
  # @since 2.0.0
66
75
  def documents
67
- reply.documents[0][RESULT] || explain_document ||
68
- cursor_document[FIRST_BATCH]
76
+ docs = reply.documents[0][RESULT]
77
+ docs ||= cursor_document[FIRST_BATCH] if cursor_document
78
+ docs ||= explain_document
79
+ docs
69
80
  end
70
81
 
71
82
  private
72
83
 
84
+ # This should only be called on explain responses; it will never
85
+ # return a nil result and will only be meaningful on explain responses
73
86
  def explain_document
74
- first_document[EXPLAIN] || first_document[EXPLAIN_LEGACY]
87
+ first_document[EXPLAIN] || first_document[EXPLAIN_LEGACY] || [first_document]
75
88
  end
76
89
 
77
90
  def cursor_document
@@ -50,7 +50,7 @@ module Mongo
50
50
  private
51
51
 
52
52
  def selector(server)
53
- { :name => { '$not' => /system\.|\$/ } }
53
+ {}
54
54
  end
55
55
 
56
56
  def message(server)
@@ -33,6 +33,15 @@ module Mongo
33
33
  cursor_document ? cursor_document[CURSOR_ID] : super
34
34
  end
35
35
 
36
+ # Get the post batch resume token for the result
37
+ #
38
+ # @return [ BSON::Document | nil ] The post batch resume token
39
+ #
40
+ # @api private
41
+ def post_batch_resume_token
42
+ cursor_document ? cursor_document['postBatchResumeToken'] : nil
43
+ end
44
+
36
45
  # Get the documents in the result.
37
46
  #
38
47
  # @example Get the documents.
@@ -31,9 +31,7 @@ module Mongo
31
31
  private
32
32
 
33
33
  def selector(server)
34
- (spec[SELECTOR] || {}).merge(
35
- listCollections: 1, filter: { name: { '$not' => /system\.|\$/ }}
36
- )
34
+ (spec[SELECTOR] || {}).merge(listCollections: 1)
37
35
  end
38
36
 
39
37
  def message(server)
@@ -28,8 +28,7 @@ module Mongo
28
28
  private
29
29
 
30
30
  def selector(server)
31
- (spec[SELECTOR] || {}).merge(
32
- listCollections: 1, filter: { name: { '$not' => /system\.|\$/ }})
31
+ (spec[SELECTOR] || {}).merge(listCollections: 1)
33
32
  end
34
33
  end
35
34
  end
@@ -32,7 +32,10 @@ module Mongo
32
32
 
33
33
  def selector(server)
34
34
  sel = { :parallelCollectionScan => coll_name, :numCursors => cursor_count }
35
- sel[:readConcern] = read_concern if read_concern
35
+ if read_concern
36
+ sel[:readConcern] = Options::Mapper.transform_values_to_strings(
37
+ read_concern)
38
+ end
36
39
  sel[:maxTimeMS] = max_time_ms if max_time_ms
37
40
  update_selector_for_read_pref(sel, server)
38
41
  sel
@@ -31,7 +31,10 @@ module Mongo
31
31
  def selector(server)
32
32
  sel = { :parallelCollectionScan => coll_name, :numCursors => cursor_count }
33
33
  sel[:maxTimeMS] = max_time_ms if max_time_ms
34
- sel[:readConcern] = read_concern if read_concern
34
+ if read_concern
35
+ sel[:readConcern] = Options::Mapper.transform_values_to_strings(
36
+ read_concern)
37
+ end
35
38
  sel
36
39
  end
37
40
  end
@@ -268,15 +268,34 @@ module Mongo
268
268
  !successful? ? raise_operation_failure : self
269
269
  end
270
270
 
271
- def raise_operation_failure
272
- raise Error::OperationFailure.new(
271
+ # The exception instance (of the Error::OperationFailure class)
272
+ # that would be raised during processing of this result.
273
+ #
274
+ # This method should only be called when result is not successful.
275
+ #
276
+ # @return [ Error::OperationFailure ] The exception.
277
+ #
278
+ # @api private
279
+ def error
280
+ @error ||= Error::OperationFailure.new(
273
281
  parser.message,
274
282
  self,
275
283
  code: parser.code,
276
284
  code_name: parser.code_name,
285
+ write_concern_error: parser.write_concern_error?,
286
+ write_concern_error_code: parser.write_concern_error_code,
287
+ write_concern_error_code_name: parser.write_concern_error_code_name,
277
288
  labels: parser.labels,
278
289
  wtimeout: parser.wtimeout)
279
290
  end
291
+
292
+ # Raises a Mongo::OperationFailure exception corresponding to the
293
+ # error information in this result.
294
+ #
295
+ # @raise Error::OperationFailure
296
+ def raise_operation_failure
297
+ raise error
298
+ end
280
299
  private :raise_operation_failure
281
300
 
282
301
  # Get the number of documents written by the server.
@@ -313,11 +332,15 @@ module Mongo
313
332
  # @example Get the cluster time.
314
333
  # result.cluster_time
315
334
  #
316
- # @return [ BSON::Document ] The cluster time document.
335
+ # @return [ nil | ClusterTime ] The cluster time document.
336
+ #
337
+ # Changed in version 2.9.0: This attribute became an instance of
338
+ # ClusterTime, which is a subclass of BSON::Document.
339
+ # Previously it was an instance of BSON::Document.
317
340
  #
318
341
  # @since 2.5.0
319
342
  def cluster_time
320
- first_document && first_document[CLUSTER_TIME]
343
+ first_document && ClusterTime[first_document['$clusterTime']]
321
344
  end
322
345
 
323
346
  # Gets the set of error labels associated with the result.
@@ -20,10 +20,20 @@ module Mongo
20
20
  # @since 2.5.2
21
21
  module Executable
22
22
 
23
+ def do_execute(server)
24
+ unpin_maybe(session) do
25
+ add_error_labels do
26
+ get_result(server).tap do |result|
27
+ process_result(result, server)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
23
33
  def execute(server)
24
- result = get_result(server)
25
- process_result(result, server)
26
- result.validate!
34
+ do_execute(server).tap do |result|
35
+ validate_result(result)
36
+ end
27
37
  end
28
38
 
29
39
  private
@@ -39,10 +49,14 @@ module Mongo
39
49
  # Returns a Protocol::Message or nil
40
50
  def dispatch_message(server)
41
51
  server.with_connection do |connection|
42
- connection.dispatch([ message(server) ], operation_id)
52
+ connection.dispatch([ build_message(server) ], operation_id)
43
53
  end
44
54
  end
45
55
 
56
+ def build_message(server)
57
+ message(server)
58
+ end
59
+
46
60
  def process_result(result, server)
47
61
  server.update_cluster_time(result)
48
62
 
@@ -52,7 +66,7 @@ module Mongo
52
66
  else
53
67
  # Max wire version needs to be checked prior to marking the
54
68
  # server unknown
55
- disconnect_pool = server.description.max_wire_version < 8
69
+ disconnect_pool = !server.description.server_version_gte?('4.2')
56
70
  end
57
71
 
58
72
  server.unknown!
@@ -22,8 +22,7 @@ module Mongo
22
22
  module ExecutableNoValidate
23
23
 
24
24
  def execute(server)
25
- result = get_result(server)
26
- process_result(result, server)
25
+ do_execute(server)
27
26
  end
28
27
  end
29
28
  end
@@ -22,15 +22,6 @@ module Mongo
22
22
  #
23
23
  # @api private
24
24
  module ExecutableTransactionLabel
25
-
26
- def execute(server)
27
- super
28
- rescue Mongo::Error::SocketError => e
29
- if session && session.in_transaction?
30
- e.send(:add_label, Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL)
31
- end
32
- raise e
33
- end
34
25
  end
35
26
  end
36
27
  end
@@ -27,8 +27,16 @@ module Mongo
27
27
 
28
28
  private
29
29
 
30
+ def self.included(base)
31
+ base.extend ClassMethods
32
+ end
33
+
34
+ module ClassMethods
35
+ attr_accessor :result_class
36
+ end
37
+
30
38
  def result_class
31
- begin
39
+ self.class.result_class ||= begin
32
40
  polymorphic_class(self.class.name, :Result)
33
41
  rescue NameError
34
42
  polymorphic_class(self.class.name.sub(/::[^:]*$/, ''), :Result)
@@ -34,7 +34,7 @@ module Mongo
34
34
  def aggregate_write_errors(count)
35
35
  return unless @replies
36
36
  @replies.reduce(nil) do |errors, reply|
37
- if write_errors = reply.documents.first[Error::WRITE_ERRORS]
37
+ if write_errors = reply.documents.first['writeErrors']
38
38
  wes = write_errors.collect do |we|
39
39
  we.merge!('index' => count + we['index'])
40
40
  end
@@ -56,7 +56,7 @@ module Mongo
56
56
  def aggregate_write_concern_errors(count)
57
57
  return unless @replies
58
58
  @replies.each_with_index.reduce(nil) do |errors, (reply, _)|
59
- if write_concern_errors = reply.documents.first[Error::WRITE_CONCERN_ERRORS]
59
+ if write_concern_errors = reply.documents.first['writeConcernErrors']
60
60
  (errors || []) << write_concern_errors.reduce(nil) do |errs, wce|
61
61
  wce.merge!('index' => count + wce['index'])
62
62
  (errs || []) << write_concern_error
@@ -62,7 +62,9 @@ module Mongo
62
62
  if !server.standalone?
63
63
  cc_doc = session.send(:causal_consistency_doc)
64
64
  if cc_doc
65
- selector[:readConcern] = (selector[:readConcern] || read_concern || {}).merge(cc_doc)
65
+ rc_doc = (selector[:readConcern] || read_concern || {}).merge(cc_doc)
66
+ selector[:readConcern] = Options::Mapper.transform_values_to_strings(
67
+ rc_doc)
66
68
  end
67
69
  end
68
70
  end
@@ -73,12 +75,10 @@ module Mongo
73
75
 
74
76
  def apply_cluster_time!(selector, server)
75
77
  if !server.standalone?
76
- cluster_time = [server.cluster_time, (session && session.cluster_time)].max_by do |doc|
77
- (doc && doc[Cluster::CLUSTER_TIME]) || ZERO_TIMESTAMP
78
- end
78
+ cluster_time = [server.cluster_time, session && session.cluster_time].compact.max
79
79
 
80
- if cluster_time && (cluster_time[Cluster::CLUSTER_TIME] > ZERO_TIMESTAMP)
81
- selector[CLUSTER_TIME] = cluster_time
80
+ if cluster_time
81
+ selector['$clusterTime'] = cluster_time
82
82
  end
83
83
  end
84
84
  end
@@ -123,46 +123,56 @@ module Mongo
123
123
  session.validate_read_preference!(selector) if read_command?(selector)
124
124
  end
125
125
 
126
- def update_session_state!
127
- session.update_state!
128
- end
129
-
130
126
  def command(server)
131
127
  sel = selector(server).dup
132
128
  add_write_concern!(sel)
133
129
  sel[Protocol::Msg::DATABASE_IDENTIFIER] = db_name
134
- sel['$readPreference'] = read.to_doc if read
130
+ unless server.standalone?
131
+ sel['$readPreference'] = read.to_doc if read
132
+ end
135
133
 
136
134
  if server.features.sessions_enabled?
137
135
  apply_cluster_time!(sel, server)
138
136
  if session && (acknowledged_write? || session.in_transaction?)
139
- sel[:txnNumber] = BSON::Int64.new(txn_num) if txn_num
140
- apply_session_id!(sel)
141
- apply_start_transaction!(sel)
142
- apply_causal_consistency!(sel, server)
143
- apply_autocommit!(sel)
144
- apply_txn_opts!(sel)
145
- suppress_read_write_concern!(sel)
146
- validate_read_preference!(sel)
147
- update_session_state!
148
- apply_txn_num!(sel)
137
+ apply_session_options(sel, server)
149
138
  end
150
139
  elsif session && session.explicit?
151
- apply_cluster_time!(sel, server)
152
- sel[:txnNumber] = BSON::Int64.new(txn_num) if txn_num
153
- apply_session_id!(sel)
154
- apply_start_transaction!(sel)
155
- apply_causal_consistency!(sel, server)
156
- apply_autocommit!(sel)
157
- apply_txn_opts!(sel)
158
- suppress_read_write_concern!(sel)
159
- validate_read_preference!(sel)
160
- update_session_state!
161
- apply_txn_num!(sel)
140
+ apply_session_options(sel, server)
162
141
  end
163
142
 
164
143
  sel
165
144
  end
145
+
146
+ def apply_session_options(sel, server)
147
+ apply_cluster_time!(sel, server)
148
+ sel[:txnNumber] = BSON::Int64.new(txn_num) if txn_num
149
+ apply_session_id!(sel)
150
+ apply_start_transaction!(sel)
151
+ apply_causal_consistency!(sel, server)
152
+ apply_autocommit!(sel)
153
+ apply_txn_opts!(sel)
154
+ suppress_read_write_concern!(sel)
155
+ validate_read_preference!(sel)
156
+ apply_txn_num!(sel)
157
+ if session.recovery_token &&
158
+ (sel[:commitTransaction] || sel[:abortTransaction])
159
+ then
160
+ sel[:recoveryToken] = session.recovery_token
161
+ end
162
+ end
163
+
164
+ def build_message(server)
165
+ super.tap do |message|
166
+ if session
167
+ # Serialize the message to detect client-side problems,
168
+ # such as invalid BSON keys. The message will be serialized again
169
+ # later prior to being sent to the server.
170
+ message.serialize(BSON::ByteBuffer.new)
171
+
172
+ session.update_state!
173
+ end
174
+ end
175
+ end
166
176
  end
167
177
  end
168
178
  end