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
@@ -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