mongo 2.4.3 → 2.5.0.beta

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 (235) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -2
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +3 -2
  5. data/lib/mongo/auth/cr.rb +6 -4
  6. data/lib/mongo/auth/cr/conversation.rb +33 -17
  7. data/lib/mongo/auth/ldap.rb +4 -2
  8. data/lib/mongo/auth/ldap/conversation.rb +19 -9
  9. data/lib/mongo/auth/scram.rb +7 -4
  10. data/lib/mongo/auth/scram/conversation.rb +62 -24
  11. data/lib/mongo/auth/user.rb +10 -0
  12. data/lib/mongo/auth/user/view.rb +44 -22
  13. data/lib/mongo/auth/x509.rb +4 -2
  14. data/lib/mongo/auth/x509/conversation.rb +19 -9
  15. data/lib/mongo/bulk_write.rb +33 -27
  16. data/lib/mongo/bulk_write/combineable.rb +5 -0
  17. data/lib/mongo/bulk_write/transformable.rb +2 -0
  18. data/lib/mongo/bulk_write/validatable.rb +4 -0
  19. data/lib/mongo/client.rb +123 -12
  20. data/lib/mongo/cluster.rb +52 -11
  21. data/lib/mongo/cluster/app_metadata.rb +8 -2
  22. data/lib/mongo/cluster/cursor_reaper.rb +0 -1
  23. data/lib/mongo/cluster/topology.rb +1 -1
  24. data/lib/mongo/collection.rb +114 -27
  25. data/lib/mongo/collection/view.rb +8 -2
  26. data/lib/mongo/collection/view/aggregation.rb +11 -7
  27. data/lib/mongo/collection/view/builder/aggregation.rb +5 -1
  28. data/lib/mongo/collection/view/builder/find_command.rb +5 -3
  29. data/lib/mongo/collection/view/builder/map_reduce.rb +11 -3
  30. data/lib/mongo/collection/view/builder/op_query.rb +1 -1
  31. data/lib/mongo/collection/view/change_stream.rb +160 -0
  32. data/lib/mongo/collection/view/change_stream/retryable.rb +57 -0
  33. data/lib/mongo/collection/view/iterable.rb +11 -10
  34. data/lib/mongo/collection/view/map_reduce.rb +22 -18
  35. data/lib/mongo/collection/view/readable.rb +51 -37
  36. data/lib/mongo/collection/view/writable.rb +72 -40
  37. data/lib/mongo/cursor.rb +25 -4
  38. data/lib/mongo/cursor/builder/get_more_command.rb +4 -2
  39. data/lib/mongo/database.rb +22 -11
  40. data/lib/mongo/database/view.rb +16 -12
  41. data/lib/mongo/error.rb +5 -0
  42. data/lib/mongo/error/invalid_session.rb +36 -0
  43. data/lib/mongo/error/missing_resume_token.rb +39 -0
  44. data/lib/mongo/error/operation_failure.rb +17 -0
  45. data/lib/mongo/error/parser.rb +3 -2
  46. data/lib/mongo/error/unknown_payload_type.rb +41 -0
  47. data/lib/mongo/error/unsupported_array_filters.rb +51 -0
  48. data/lib/mongo/error/unsupported_message_type.rb +23 -0
  49. data/lib/mongo/grid/fs_bucket.rb +5 -4
  50. data/lib/mongo/grid/stream/read.rb +3 -2
  51. data/lib/mongo/grid/stream/write.rb +2 -2
  52. data/lib/mongo/index/view.rb +35 -25
  53. data/lib/mongo/monitoring/event/secure.rb +14 -0
  54. data/lib/mongo/operation.rb +16 -0
  55. data/lib/mongo/operation/commands.rb +1 -0
  56. data/lib/mongo/operation/commands/aggregate.rb +9 -5
  57. data/lib/mongo/operation/commands/aggregate/result.rb +1 -1
  58. data/lib/mongo/operation/commands/collections_info.rb +6 -6
  59. data/lib/mongo/operation/commands/command.rb +2 -1
  60. data/lib/mongo/operation/commands/create.rb +6 -2
  61. data/lib/mongo/operation/commands/drop.rb +6 -2
  62. data/lib/mongo/operation/commands/drop_database.rb +6 -2
  63. data/lib/mongo/operation/commands/explain.rb +27 -0
  64. data/lib/mongo/operation/commands/explain/result.rb +52 -0
  65. data/lib/mongo/operation/commands/indexes.rb +1 -1
  66. data/lib/mongo/operation/commands/list_collections.rb +1 -1
  67. data/lib/mongo/operation/commands/list_collections/result.rb +1 -1
  68. data/lib/mongo/operation/commands/list_indexes.rb +1 -1
  69. data/lib/mongo/operation/commands/list_indexes/result.rb +1 -1
  70. data/lib/mongo/operation/commands/map_reduce.rb +8 -4
  71. data/lib/mongo/operation/commands/map_reduce/result.rb +13 -1
  72. data/lib/mongo/operation/commands/user_query.rb +1 -1
  73. data/lib/mongo/operation/commands/users_info.rb +6 -2
  74. data/lib/mongo/operation/executable.rb +4 -1
  75. data/lib/mongo/operation/read_preference.rb +10 -5
  76. data/lib/mongo/operation/result.rb +26 -2
  77. data/lib/mongo/operation/specifiable.rb +13 -1
  78. data/lib/mongo/operation/uses_command_op_msg.rb +47 -0
  79. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -1
  80. data/lib/mongo/operation/write/bulk/insert/result.rb +4 -4
  81. data/lib/mongo/operation/write/command/create_index.rb +6 -1
  82. data/lib/mongo/operation/write/command/delete.rb +28 -4
  83. data/lib/mongo/operation/write/command/drop_index.rb +6 -1
  84. data/lib/mongo/operation/write/command/insert.rb +22 -18
  85. data/lib/mongo/operation/write/command/update.rb +24 -9
  86. data/lib/mongo/operation/write/command/writable.rb +14 -1
  87. data/lib/mongo/operation/write/insert.rb +4 -1
  88. data/lib/mongo/operation/write/insert/result.rb +2 -2
  89. data/lib/mongo/operation/write/update.rb +7 -1
  90. data/lib/mongo/operation/write/write_command_enabled.rb +20 -3
  91. data/lib/mongo/protocol.rb +3 -0
  92. data/lib/mongo/protocol/bit_vector.rb +2 -2
  93. data/lib/mongo/protocol/compressed.rb +135 -0
  94. data/lib/mongo/protocol/delete.rb +8 -6
  95. data/lib/mongo/protocol/get_more.rb +8 -6
  96. data/lib/mongo/protocol/insert.rb +8 -6
  97. data/lib/mongo/protocol/kill_cursors.rb +8 -6
  98. data/lib/mongo/protocol/message.rb +31 -3
  99. data/lib/mongo/protocol/msg.rb +172 -0
  100. data/lib/mongo/protocol/query.rb +26 -6
  101. data/lib/mongo/protocol/registry.rb +76 -0
  102. data/lib/mongo/protocol/reply.rb +10 -5
  103. data/lib/mongo/protocol/serializers.rb +224 -0
  104. data/lib/mongo/protocol/update.rb +8 -6
  105. data/lib/mongo/retryable.rb +4 -2
  106. data/lib/mongo/server.rb +6 -3
  107. data/lib/mongo/server/connectable.rb +1 -1
  108. data/lib/mongo/server/connection.rb +30 -8
  109. data/lib/mongo/server/description.rb +25 -1
  110. data/lib/mongo/server/description/features.rb +4 -1
  111. data/lib/mongo/server/monitor.rb +5 -0
  112. data/lib/mongo/server/monitor/connection.rb +50 -2
  113. data/lib/mongo/server_selector/nearest.rb +10 -4
  114. data/lib/mongo/server_selector/primary.rb +20 -0
  115. data/lib/mongo/server_selector/primary_preferred.rb +10 -4
  116. data/lib/mongo/server_selector/secondary.rb +10 -4
  117. data/lib/mongo/server_selector/secondary_preferred.rb +24 -4
  118. data/lib/mongo/session.rb +180 -0
  119. data/lib/mongo/session/server_session.rb +73 -0
  120. data/lib/mongo/session/session_pool.rb +161 -0
  121. data/lib/mongo/uri.rb +11 -0
  122. data/lib/mongo/version.rb +1 -1
  123. data/mongo.gemspec +2 -1
  124. data/spec/mongo/auth/cr_spec.rb +12 -0
  125. data/spec/mongo/auth/ldap_spec.rb +2 -0
  126. data/spec/mongo/auth/scram/conversation_spec.rb +6 -6
  127. data/spec/mongo/auth/scram_spec.rb +25 -1
  128. data/spec/mongo/auth/user/view_spec.rb +268 -76
  129. data/spec/mongo/auth/x509_spec.rb +2 -0
  130. data/spec/mongo/bulk_write_spec.rb +435 -5
  131. data/spec/mongo/client_spec.rb +356 -39
  132. data/spec/mongo/cluster/app_metadata_spec.rb +2 -2
  133. data/spec/mongo/cluster_spec.rb +176 -0
  134. data/spec/mongo/collection/view/aggregation_spec.rb +33 -12
  135. data/spec/mongo/collection/view/builder/find_command_spec.rb +46 -6
  136. data/spec/mongo/collection/view/change_stream_spec.rb +814 -0
  137. data/spec/mongo/collection/view/map_reduce_spec.rb +94 -17
  138. data/spec/mongo/collection/view/readable_spec.rb +3 -12
  139. data/spec/mongo/collection_spec.rb +1048 -42
  140. data/spec/mongo/cursor/builder/get_more_command_spec.rb +19 -0
  141. data/spec/mongo/cursor_spec.rb +2 -2
  142. data/spec/mongo/database_spec.rb +50 -1
  143. data/spec/mongo/grid/fs_bucket_spec.rb +225 -137
  144. data/spec/mongo/grid/stream/read_spec.rb +2 -2
  145. data/spec/mongo/index/view_spec.rb +146 -8
  146. data/spec/mongo/monitoring/event/secure_spec.rb +42 -0
  147. data/spec/mongo/operation/read/query_spec.rb +2 -1
  148. data/spec/mongo/operation/specifiable_spec.rb +2 -2
  149. data/spec/mongo/operation/write/command/delete_spec.rb +96 -13
  150. data/spec/mongo/operation/write/command/insert_spec.rb +111 -12
  151. data/spec/mongo/operation/write/command/update_spec.rb +93 -10
  152. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  153. data/spec/mongo/operation/write/insert_spec.rb +1 -1
  154. data/spec/mongo/operation/write/update_spec.rb +1 -1
  155. data/spec/mongo/protocol/compressed_spec.rb +66 -0
  156. data/spec/mongo/protocol/delete_spec.rb +14 -0
  157. data/spec/mongo/protocol/get_more_spec.rb +14 -0
  158. data/spec/mongo/protocol/insert_spec.rb +14 -0
  159. data/spec/mongo/protocol/kill_cursors_spec.rb +14 -0
  160. data/spec/mongo/protocol/msg_spec.rb +499 -0
  161. data/spec/mongo/protocol/query_spec.rb +45 -0
  162. data/spec/mongo/protocol/registry_spec.rb +31 -0
  163. data/spec/mongo/protocol/reply_spec.rb +14 -0
  164. data/spec/mongo/protocol/update_spec.rb +14 -0
  165. data/spec/mongo/retryable_spec.rb +6 -2
  166. data/spec/mongo/sdam_spec.rb +4 -0
  167. data/spec/mongo/server/connection_spec.rb +4 -2
  168. data/spec/mongo/server/description_spec.rb +28 -1
  169. data/spec/mongo/session/server_session_spec.rb +16 -0
  170. data/spec/mongo/session/session_pool_spec.rb +194 -0
  171. data/spec/mongo/uri_spec.rb +31 -2
  172. data/spec/spec_helper.rb +104 -0
  173. data/spec/support/authorization.rb +6 -1
  174. data/spec/support/crud.rb +3 -1
  175. data/spec/support/crud/write.rb +6 -1
  176. data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +69 -0
  177. data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +63 -0
  178. data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +109 -0
  179. data/spec/support/sdam/rs/discover_arbiters.yml +1 -1
  180. data/spec/support/sdam/rs/discover_passives.yml +2 -2
  181. data/spec/support/sdam/rs/discover_primary.yml +1 -1
  182. data/spec/support/sdam/rs/discover_secondary.yml +1 -1
  183. data/spec/support/sdam/rs/discovery.yml +4 -4
  184. data/spec/support/sdam/rs/equal_electionids.yml +1 -0
  185. data/spec/support/sdam/rs/ghost_discovered.yml +1 -1
  186. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +1 -1
  187. data/spec/support/sdam/rs/ls_timeout.yml +88 -0
  188. data/spec/support/sdam/rs/member_reconfig.yml +2 -2
  189. data/spec/support/sdam/rs/member_standalone.yml +2 -2
  190. data/spec/support/sdam/rs/new_primary.yml +2 -2
  191. data/spec/support/sdam/rs/new_primary_new_electionid.yml +3 -0
  192. data/spec/support/sdam/rs/new_primary_new_setversion.yml +3 -0
  193. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +2 -2
  194. data/spec/support/sdam/rs/non_rs_member.yml +1 -1
  195. data/spec/support/sdam/rs/normalize_case.yml +1 -1
  196. data/spec/support/sdam/rs/null_election_id.yml +4 -0
  197. data/spec/support/sdam/rs/primary_becomes_standalone.yml +2 -2
  198. data/spec/support/sdam/rs/primary_changes_set_name.yml +2 -2
  199. data/spec/support/sdam/rs/primary_disconnect.yml +2 -2
  200. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +5 -0
  201. data/spec/support/sdam/rs/primary_disconnect_setversion.yml +5 -0
  202. data/spec/support/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +58 -0
  203. data/spec/support/sdam/rs/primary_reports_new_member.yml +4 -4
  204. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +2 -2
  205. data/spec/support/sdam/rs/primary_wrong_set_name.yml +1 -1
  206. data/spec/support/sdam/rs/response_from_removed.yml +2 -2
  207. data/spec/support/sdam/rs/rsother_discovered.yml +1 -1
  208. data/spec/support/sdam/rs/sec_not_auth.yml +1 -1
  209. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +1 -1
  210. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +2 -2
  211. data/spec/support/sdam/rs/setversion_without_electionid.yml +2 -0
  212. data/spec/support/sdam/rs/stepdown_change_set_name.yml +2 -2
  213. data/spec/support/sdam/rs/unexpected_mongos.yml +1 -1
  214. data/spec/support/sdam/rs/use_setversion_without_electionid.yml +3 -0
  215. data/spec/support/sdam/rs/wrong_set_name.yml +1 -1
  216. data/spec/support/sdam/sharded/ls_timeout_mongos.yml +97 -0
  217. data/spec/support/sdam/sharded/mongos_disconnect.yml +3 -3
  218. data/spec/support/sdam/sharded/multiple_mongoses.yml +1 -1
  219. data/spec/support/sdam/sharded/non_mongos_removed.yml +1 -1
  220. data/spec/support/sdam/sharded/normalize_uri_case.yml +1 -1
  221. data/spec/support/sdam/single/direct_connection_external_ip.yml +1 -1
  222. data/spec/support/sdam/single/direct_connection_mongos.yml +1 -1
  223. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  224. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  225. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  226. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  227. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  228. data/spec/support/sdam/single/ls_timeout_standalone.yml +35 -0
  229. data/spec/support/sdam/single/not_ok_response.yml +1 -1
  230. data/spec/support/sdam/single/standalone_removed.yml +1 -1
  231. data/spec/support/sdam/single/unavailable_seed.yml +1 -1
  232. data/spec/support/server_discovery_and_monitoring.rb +4 -0
  233. data/spec/support/shared/session.rb +236 -0
  234. metadata +53 -15
  235. metadata.gz.sig +0 -0
@@ -19,7 +19,7 @@ module Mongo
19
19
  # A MongoDB listCollections command operation.
20
20
  #
21
21
  # @example Create the listCollections command operation.
22
- # Mongo::Operation::Read::ListCollections.new(db_name: 'test')
22
+ # ListCollections.new(db_name: 'test')
23
23
  #
24
24
  # @note A command is actually a query on the virtual '$cmd' collection.
25
25
  #
@@ -75,7 +75,7 @@ module Mongo
75
75
  #
76
76
  # @since 2.0.0
77
77
  def validate!
78
- !successful? ? raise(Error::OperationFailure.new(parser.message)) : self
78
+ !successful? ? raise(Error::OperationFailure.new(parser.message, self)) : self
79
79
  end
80
80
 
81
81
  private
@@ -19,7 +19,7 @@ module Mongo
19
19
  # A MongoDB listIndexes command operation.
20
20
  #
21
21
  # @example Create the listIndexes command operation.
22
- # Mongo::Operation::Read::ListIndexes.new({ db_name: 'test', coll_name: 'example' })
22
+ # ListIndexes.new({ db_name: 'test', coll_name: 'example' })
23
23
  #
24
24
  # @note A command is actually a query on the virtual '$cmd' collection.
25
25
  #
@@ -79,7 +79,7 @@ module Mongo
79
79
  #
80
80
  # @since 2.0.0
81
81
  def validate!
82
- !successful? ? raise(Error::OperationFailure.new(parser.message)) : self
82
+ !successful? ? raise(Error::OperationFailure.new(parser.message, self)) : self
83
83
  end
84
84
 
85
85
  private
@@ -47,10 +47,14 @@ module Mongo
47
47
  private
48
48
 
49
49
  def message(server)
50
- sel = update_selector_for_read_pref(selector, server)
51
- sel = update_selector_for_write_concern(sel, server)
52
- opts = update_options_for_slave_ok(options, server)
53
- Protocol::Query.new(db_name, query_coll, sel, opts)
50
+ sel = update_selector_for_write_concern(selector, server)
51
+ if server.features.op_msg_enabled?
52
+ command_op_msg(server, sel, options)
53
+ else
54
+ sel = update_selector_for_read_pref(sel, server)
55
+ opts = update_options_for_slave_ok(options, server)
56
+ Protocol::Query.new(db_name, query_coll, sel, opts)
57
+ end
54
58
  end
55
59
  end
56
60
  end
@@ -104,7 +104,19 @@ module Mongo
104
104
  #
105
105
  # @since 2.0.0
106
106
  def validate!
107
- documents.nil? ? raise(Error::OperationFailure.new(parser.message)) : self
107
+ documents.nil? ? raise(Error::OperationFailure.new(parser.message, self)) : self
108
+ end
109
+
110
+ # Get the cursor id.
111
+ #
112
+ # @example Get the cursor id.
113
+ # result.cursor_id
114
+ #
115
+ # @return [ Integer ] Always 0 because map reduce doesn't return a cursor.
116
+ #
117
+ # @since 2.5.0
118
+ def cursor_id
119
+ 0
108
120
  end
109
121
 
110
122
  private
@@ -19,7 +19,7 @@ module Mongo
19
19
  # A MongoDB operation to get info of a particular user in a database.
20
20
  #
21
21
  # @example Create the user query operation.
22
- # Read::UserQuery.new(:name => 'emily', :db_name => 'test-db')
22
+ # UserQuery.new(:name => 'emily', :db_name => 'test-db')
23
23
  #
24
24
  # Initialization:
25
25
  # param [ Hash ] spec The specifications for the user query operation.
@@ -19,7 +19,7 @@ module Mongo
19
19
  # A MongoDB operation to get info of a particular user in a database.
20
20
  #
21
21
  # @example Create the users info operation.
22
- # Read::UsersInfo.new(:name => 'emily', :db_name => 'test-db')
22
+ # UsersInfo.new(:name => 'emily', :db_name => 'test-db')
23
23
  #
24
24
  # Initialization:
25
25
  # param [ Hash ] spec The specifications for the users info operation.
@@ -38,7 +38,11 @@ module Mongo
38
38
  end
39
39
 
40
40
  def message(server)
41
- Protocol::Query.new(db_name, query_coll, selector, options)
41
+ if server.features.op_msg_enabled?
42
+ command_op_msg(server, selector, options)
43
+ else
44
+ Protocol::Query.new(db_name, query_coll, selector, options)
45
+ end
42
46
  end
43
47
  end
44
48
  end
@@ -34,7 +34,10 @@ module Mongo
34
34
  def execute(server)
35
35
  server.with_connection do |connection|
36
36
  result_class = self.class.const_defined?(:Result, false) ? self.class::Result : Result
37
- result_class.new(connection.dispatch([ message(server) ], operation_id)).validate!
37
+ result = result_class.new(connection.dispatch([ message(server) ], operation_id))
38
+ server.update_cluster_time(result)
39
+ session.process(result) if session
40
+ result.validate!
38
41
  end
39
42
  end
40
43
  end
@@ -20,6 +20,7 @@ module Mongo
20
20
  #
21
21
  # @since 2.0.0
22
22
  module ReadPreference
23
+ include UsesCommandOpMsg
23
24
 
24
25
  # The constant for slave ok flags.
25
26
  #
@@ -29,7 +30,7 @@ module Mongo
29
30
  private
30
31
 
31
32
  def update_selector_for_read_pref(sel, server)
32
- if server.mongos? && read_pref = read.to_mongos
33
+ if read && server.mongos? && read_pref = read.to_mongos
33
34
  sel = sel[:$query] ? sel : { :$query => sel }
34
35
  sel.merge(:$readPreference => read_pref)
35
36
  else
@@ -38,7 +39,7 @@ module Mongo
38
39
  end
39
40
 
40
41
  def slave_ok?(server)
41
- (server.cluster.single? && !server.mongos?) || read.slave_ok?
42
+ (server.cluster.single? && !server.mongos?) || (read && read.slave_ok?)
42
43
  end
43
44
 
44
45
  def update_options_for_slave_ok(opts, server)
@@ -52,9 +53,13 @@ module Mongo
52
53
  end
53
54
 
54
55
  def message(server)
55
- sel = update_selector_for_read_pref(selector, server)
56
- opts = update_options_for_slave_ok(options, server)
57
- Protocol::Query.new(db_name, query_coll, sel, opts)
56
+ if server.features.op_msg_enabled?
57
+ command_op_msg(server, selector, options)
58
+ else
59
+ sel = update_selector_for_read_pref(selector, server)
60
+ opts = update_options_for_slave_ok(options, server)
61
+ Protocol::Query.new(db_name, query_coll, sel, opts)
62
+ end
58
63
  end
59
64
  end
60
65
  end
@@ -158,7 +158,7 @@ module Mongo
158
158
  #
159
159
  # @since 2.0.0
160
160
  def initialize(replies)
161
- @replies = replies.is_a?(Protocol::Reply) ? [ replies ] : replies
161
+ @replies = [ *replies ] if replies
162
162
  end
163
163
 
164
164
  # Get the pretty formatted inspection of the result.
@@ -253,7 +253,7 @@ module Mongo
253
253
  #
254
254
  # @since 2.0.0
255
255
  def validate!
256
- !successful? ? raise(Error::OperationFailure.new(parser.message)) : self
256
+ !successful? ? raise(Error::OperationFailure.new(parser.message, self)) : self
257
257
  end
258
258
 
259
259
  # Get the number of documents written by the server.
@@ -273,6 +273,30 @@ module Mongo
273
273
  end
274
274
  alias :n :written_count
275
275
 
276
+ # Get the operation time reported in the server response.
277
+ #
278
+ # @example Get the operation time.
279
+ # result.operation_time
280
+ #
281
+ # @return [ Object ] The operation time value.
282
+ #
283
+ # @since 2.5.0
284
+ def operation_time
285
+ first_document && first_document[OPERATION_TIME]
286
+ end
287
+
288
+ # Get the cluster time reported in the server response.
289
+ #
290
+ # @example Get the cluster time.
291
+ # result.cluster_time
292
+ #
293
+ # @return [ BSON::Document ] The cluster time document.
294
+ #
295
+ # @since 2.5.0
296
+ def cluster_time
297
+ first_document && first_document[CLUSTER_TIME]
298
+ end
299
+
276
300
  private
277
301
 
278
302
  def aggregate_returned_count
@@ -476,7 +476,7 @@ module Mongo
476
476
  #
477
477
  # @since 2.0.0
478
478
  def read
479
- @read ||= ServerSelector.get(@spec[READ] || ServerSelector::PRIMARY)
479
+ @read ||= ServerSelector.get(spec[READ]) if spec[READ]
480
480
  end
481
481
 
482
482
  # Whether the operation is ordered.
@@ -502,6 +502,18 @@ module Mongo
502
502
  def namespace
503
503
  "#{db_name}.#{coll_name}"
504
504
  end
505
+
506
+ # The session to use for the operation.
507
+ #
508
+ # @example Get the session.
509
+ # specifiable.session
510
+ #
511
+ # @return [ Session ] The session.
512
+ #
513
+ # @since 2.5.0
514
+ def session
515
+ @spec[:session]
516
+ end
505
517
  end
506
518
  end
507
519
  end
@@ -0,0 +1,47 @@
1
+ # Copyright (C) 2017 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Operation
17
+
18
+ # A command that uses OP_MSG, with the document as payload type 0.
19
+ #
20
+ # @since 2.5.0
21
+ module UsesCommandOpMsg
22
+
23
+ private
24
+
25
+ READ_PREFERENCE = '$readPreference'.freeze
26
+
27
+ def add_cluster_time!(selector, server)
28
+ if cluster_time = server.mongos? && server.cluster_time
29
+ selector[CLUSTER_TIME] = cluster_time
30
+ end
31
+ end
32
+
33
+ def unacknowledged_write?
34
+ write_concern && write_concern.get_last_error.nil?
35
+ end
36
+
37
+ def command_op_msg(server, selector, options)
38
+ add_cluster_time!(selector, server)
39
+ selector[Protocol::Msg::DATABASE_IDENTIFIER] = db_name
40
+ selector[READ_PREFERENCE] = read.to_doc if read
41
+ session.add_id!(selector) if session
42
+ flags = unacknowledged_write? ? [:more_to_come] : [:none]
43
+ Protocol::Msg.new(flags, options, selector)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -36,7 +36,10 @@ module Mongo
36
36
  # @since 2.0.0
37
37
  def execute(server)
38
38
  if server.features.write_command_enabled?
39
- execute_write_command(server)
39
+ result = execute_write_command(server)
40
+ server.update_cluster_time(result)
41
+ session.process(result) if session
42
+ result
40
43
  else
41
44
  execute_message(server)
42
45
  end
@@ -34,12 +34,12 @@ module Mongo
34
34
  # @example Instantiate the result.
35
35
  # Result.new(replies, inserted_ids)
36
36
  #
37
- # @param [ Protocol::Reply ] replies The wire protocol replies.
37
+ # @param [ Protocol::Message ] replies The wire protocol replies.
38
38
  # @param [ Array<Object> ] ids The ids of the inserted documents.
39
39
  #
40
40
  # @since 2.0.0
41
41
  def initialize(replies, ids)
42
- @replies = replies.is_a?(Protocol::Reply) ? [ replies ] : replies
42
+ @replies = [ *replies ] if replies
43
43
  @inserted_ids = ids
44
44
  end
45
45
 
@@ -85,12 +85,12 @@ module Mongo
85
85
  # @example Instantiate the result.
86
86
  # Result.new(replies, inserted_ids)
87
87
  #
88
- # @param [ Protocol::Reply ] replies The wire protocol replies.
88
+ # @param [ Protocol::Message ] replies The wire protocol replies.
89
89
  # @param [ Array<Object> ] ids The ids of the inserted documents.
90
90
  #
91
91
  # @since 2.0.0
92
92
  def initialize(replies, ids)
93
- @replies = replies.is_a?(Protocol::Reply) ? [ replies ] : replies
93
+ @replies = [ *replies ] if replies
94
94
  @inserted_ids = ids
95
95
  end
96
96
 
@@ -31,6 +31,7 @@ module Mongo
31
31
  include Specifiable
32
32
  include Writable
33
33
  include TakesWriteConcern
34
+ include UsesCommandOpMsg
34
35
 
35
36
  private
36
37
 
@@ -45,7 +46,11 @@ module Mongo
45
46
 
46
47
  def message(server)
47
48
  sel = update_selector_for_write_concern(selector, server)
48
- Protocol::Query.new(db_name, Database::COMMAND, sel, options)
49
+ if server.features.op_msg_enabled?
50
+ command_op_msg(server, sel, options)
51
+ else
52
+ Protocol::Query.new(db_name, Database::COMMAND, sel, options)
53
+ end
49
54
  end
50
55
  end
51
56
  end
@@ -35,6 +35,8 @@ module Mongo
35
35
 
36
36
  private
37
37
 
38
+ IDENTIFIER = 'deletes'.freeze
39
+
38
40
  # The query selector for this delete command operation.
39
41
  #
40
42
  # @return [ Hash ] The selector describing this delete operation.
@@ -42,10 +44,32 @@ module Mongo
42
44
  # @since 2.0.0
43
45
  def selector
44
46
  { delete: coll_name,
45
- deletes: deletes,
46
- ordered: ordered?
47
- }.tap do |cmd|
48
- cmd.merge!(writeConcern: write_concern.options) if write_concern
47
+ deletes: deletes
48
+ }.merge(command_options)
49
+ end
50
+
51
+ def op_msg(server)
52
+ global_args = { delete: coll_name,
53
+ Protocol::Msg::DATABASE_IDENTIFIER => db_name
54
+ }.merge!(command_options)
55
+ add_cluster_time!(global_args, server)
56
+ session.add_id!(global_args) if session
57
+
58
+ section = { type: 1, payload: { identifier: IDENTIFIER, sequence: deletes } }
59
+ flags = unacknowledged_write? ? [:more_to_come] : [:none]
60
+ Protocol::Msg.new(flags, {}, global_args, section)
61
+ end
62
+
63
+ # The wire protocol message for this write operation.
64
+ #
65
+ # @return [ Mongo::Protocol::Query ] Wire protocol message.
66
+ #
67
+ # @since 2.0.0
68
+ def message(server)
69
+ if server.features.op_msg_enabled?
70
+ op_msg(server)
71
+ else
72
+ Protocol::Query.new(db_name, Database::COMMAND, selector, options)
49
73
  end
50
74
  end
51
75
  end
@@ -32,6 +32,7 @@ module Mongo
32
32
  include Specifiable
33
33
  include Writable
34
34
  include TakesWriteConcern
35
+ include UsesCommandOpMsg
35
36
 
36
37
  private
37
38
 
@@ -46,7 +47,11 @@ module Mongo
46
47
 
47
48
  def message(server)
48
49
  sel = update_selector_for_write_concern(selector, server)
49
- Protocol::Query.new(db_name, Database::COMMAND, sel, options)
50
+ if server.features.op_msg_enabled?
51
+ command_op_msg(server, sel, options)
52
+ else
53
+ Protocol::Query.new(db_name, Database::COMMAND, sel, options)
54
+ end
50
55
  end
51
56
  end
52
57
  end
@@ -34,29 +34,33 @@ module Mongo
34
34
 
35
35
  private
36
36
 
37
- # The query selector for this insert command operation.
38
- #
39
- # @return [ Hash ] The selector describing this insert operation.
40
- #
41
- # @since 2.0.0
37
+ IDENTIFIER = 'documents'.freeze
38
+
42
39
  def selector
43
40
  { insert: coll_name,
44
- documents: documents,
45
- ordered: ordered?
46
- }.tap do |cmd|
47
- cmd.merge!(writeConcern: write_concern.options) if write_concern
48
- cmd.merge!(:bypassDocumentValidation => true) if bypass_document_validation
49
- end
41
+ documents: documents
42
+ }.merge!(command_options)
43
+ end
44
+
45
+ def op_msg(server)
46
+ global_args = { insert: coll_name,
47
+ Protocol::Msg::DATABASE_IDENTIFIER => db_name
48
+ }.merge!(command_options)
49
+ add_cluster_time!(global_args, server)
50
+ session.add_id!(global_args) if session
51
+
52
+ section = { type: 1, payload: { identifier: IDENTIFIER, sequence: documents } }
53
+ flags = unacknowledged_write? ? [:more_to_come] : [:none]
54
+ Protocol::Msg.new(flags, { validating_keys: true }, global_args, section)
50
55
  end
51
56
 
52
- # The wire protocol message for this write operation.
53
- #
54
- # @return [ Mongo::Protocol::Query ] Wire protocol message.
55
- #
56
- # @since 2.2.5
57
57
  def message(server)
58
- opts = options.merge(validating_keys: true)
59
- Protocol::Query.new(db_name, Database::COMMAND, selector, opts)
58
+ if server.features.op_msg_enabled?
59
+ op_msg(server)
60
+ else
61
+ opts = options.merge(validating_keys: true)
62
+ Protocol::Query.new(db_name, Database::COMMAND, selector, opts)
63
+ end
60
64
  end
61
65
  end
62
66
  end