mongo 2.0.6 → 2.1.0

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 (317) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -2
  3. data/lib/mongo/address/ipv4.rb +6 -1
  4. data/lib/mongo/address/unix.rb +2 -2
  5. data/lib/mongo/address.rb +18 -10
  6. data/lib/mongo/auth/cr/conversation.rb +1 -1
  7. data/lib/mongo/auth/ldap/conversation.rb +7 -3
  8. data/lib/mongo/auth/scram/conversation.rb +9 -3
  9. data/lib/mongo/auth/user/view.rb +23 -2
  10. data/lib/mongo/auth/x509/conversation.rb +1 -1
  11. data/lib/mongo/bulk_write/combineable.rb +51 -0
  12. data/lib/mongo/bulk_write/ordered_combiner.rb +55 -0
  13. data/lib/mongo/bulk_write/result.rb +191 -0
  14. data/lib/mongo/bulk_write/result_combiner.rb +117 -0
  15. data/lib/mongo/bulk_write/transformable.rb +132 -0
  16. data/lib/mongo/bulk_write/unordered_combiner.rb +52 -0
  17. data/lib/mongo/bulk_write/validatable.rb +62 -0
  18. data/lib/mongo/bulk_write.rb +159 -23
  19. data/lib/mongo/client.rb +52 -16
  20. data/lib/mongo/cluster/topology/replica_set.rb +27 -9
  21. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  22. data/lib/mongo/cluster/topology/unknown.rb +5 -2
  23. data/lib/mongo/cluster.rb +42 -7
  24. data/lib/mongo/collection/view/aggregation.rb +48 -9
  25. data/lib/mongo/collection/view/immutable.rb +6 -6
  26. data/lib/mongo/collection/view/iterable.rb +18 -4
  27. data/lib/mongo/collection/view/map_reduce.rb +58 -17
  28. data/lib/mongo/collection/view/readable.rb +173 -42
  29. data/lib/mongo/collection/view/writable.rb +37 -23
  30. data/lib/mongo/collection/view.rb +2 -2
  31. data/lib/mongo/collection.rb +370 -33
  32. data/lib/mongo/cursor.rb +15 -3
  33. data/lib/mongo/database/view.rb +5 -4
  34. data/lib/mongo/database.rb +14 -4
  35. data/lib/mongo/dbref.rb +113 -0
  36. data/lib/mongo/error/closed_stream.rb +34 -0
  37. data/lib/mongo/error/extra_file_chunk.rb +34 -0
  38. data/lib/mongo/error/{invalid_uri_option.rb → file_not_found.rb} +11 -12
  39. data/lib/mongo/error/invalid_file.rb +2 -2
  40. data/lib/mongo/error/invalid_file_revision.rb +37 -0
  41. data/lib/mongo/error/invalid_uri.rb +5 -4
  42. data/lib/mongo/error/missing_file_chunk.rb +38 -0
  43. data/lib/mongo/error/operation_failure.rb +1 -1
  44. data/lib/mongo/error/parser.rb +1 -1
  45. data/lib/mongo/error/unchangeable_collection_option.rb +38 -0
  46. data/lib/mongo/error/unexpected_chunk_length.rb +39 -0
  47. data/lib/mongo/error.rb +13 -2
  48. data/lib/mongo/event/description_changed.rb +1 -1
  49. data/lib/mongo/grid/file/chunk.rb +6 -6
  50. data/lib/mongo/grid/file/{metadata.rb → info.rb} +41 -39
  51. data/lib/mongo/grid/file.rb +13 -10
  52. data/lib/mongo/grid/fs_bucket.rb +448 -0
  53. data/lib/mongo/grid/stream/read.rb +208 -0
  54. data/lib/mongo/grid/stream/write.rb +187 -0
  55. data/lib/mongo/grid/stream.rb +64 -0
  56. data/lib/mongo/grid.rb +2 -1
  57. data/lib/mongo/index/view.rb +3 -3
  58. data/lib/mongo/index.rb +5 -0
  59. data/lib/mongo/loggable.rb +34 -57
  60. data/lib/mongo/logger.rb +16 -78
  61. data/lib/mongo/monitoring/command_log_subscriber.rb +112 -0
  62. data/lib/mongo/monitoring/event/command_failed.rb +96 -0
  63. data/lib/mongo/monitoring/event/command_started.rb +89 -0
  64. data/lib/mongo/monitoring/event/command_succeeded.rb +118 -0
  65. data/lib/mongo/monitoring/event/secure.rb +58 -0
  66. data/lib/mongo/monitoring/event.rb +18 -0
  67. data/lib/mongo/monitoring/publishable.rb +106 -0
  68. data/lib/mongo/monitoring.rb +195 -0
  69. data/lib/mongo/operation/{aggregate.rb → commands/aggregate.rb} +3 -41
  70. data/lib/mongo/operation/commands/collections_info/result.rb +39 -0
  71. data/lib/mongo/operation/commands/collections_info.rb +68 -0
  72. data/lib/mongo/operation/{command.rb → commands/command.rb} +2 -18
  73. data/lib/mongo/operation/commands/indexes.rb +70 -0
  74. data/lib/mongo/operation/commands/list_collections/result.rb +112 -0
  75. data/lib/mongo/operation/commands/list_collections.rb +54 -0
  76. data/lib/mongo/operation/commands/list_indexes/result.rb +116 -0
  77. data/lib/mongo/operation/commands/list_indexes.rb +56 -0
  78. data/lib/mongo/operation/{map_reduce → commands/map_reduce}/result.rb +1 -1
  79. data/lib/mongo/operation/{map_reduce.rb → commands/map_reduce.rb} +3 -41
  80. data/lib/mongo/operation/commands/parallel_scan/result.rb +72 -0
  81. data/lib/mongo/operation/commands/parallel_scan.rb +56 -0
  82. data/lib/mongo/operation/commands/user_query.rb +69 -0
  83. data/lib/mongo/{bulk_write/ordered_bulk_write.rb → operation/commands/users_info/result.rb} +18 -30
  84. data/lib/mongo/operation/commands/users_info.rb +53 -0
  85. data/lib/mongo/operation/commands.rb +24 -0
  86. data/lib/mongo/operation/executable.rb +4 -68
  87. data/lib/mongo/operation/kill_cursors.rb +3 -3
  88. data/lib/mongo/operation/read/get_more.rb +2 -22
  89. data/lib/mongo/{bulk_write/unordered_bulk_write.rb → operation/read/query/result.rb} +20 -26
  90. data/lib/mongo/operation/read/query.rb +4 -21
  91. data/lib/mongo/operation/read.rb +0 -4
  92. data/lib/mongo/operation/{read_preferrable.rb → read_preference.rb} +3 -2
  93. data/lib/mongo/operation/result.rb +13 -1
  94. data/lib/mongo/operation/specifiable.rb +42 -0
  95. data/lib/mongo/operation/write/bulk/bulkable.rb +82 -0
  96. data/lib/mongo/operation/write/bulk/delete/result.rb +74 -0
  97. data/lib/mongo/operation/write/bulk/delete.rb +71 -0
  98. data/lib/mongo/operation/write/bulk/insert/result.rb +129 -0
  99. data/lib/mongo/operation/write/bulk/insert.rb +96 -0
  100. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +87 -0
  101. data/lib/mongo/operation/write/bulk/mergable.rb +71 -0
  102. data/lib/mongo/operation/write/bulk/update/result.rb +174 -0
  103. data/lib/mongo/operation/write/bulk/update.rb +81 -0
  104. data/lib/mongo/operation/write/bulk.rb +6 -3
  105. data/lib/mongo/operation/write/command/create_index.rb +0 -1
  106. data/lib/mongo/operation/write/command/create_user.rb +0 -1
  107. data/lib/mongo/operation/write/command/delete.rb +0 -1
  108. data/lib/mongo/operation/write/command/drop_index.rb +0 -1
  109. data/lib/mongo/operation/write/command/insert.rb +0 -1
  110. data/lib/mongo/operation/write/command/remove_user.rb +0 -1
  111. data/lib/mongo/operation/write/command/update.rb +0 -1
  112. data/lib/mongo/operation/write/command/update_user.rb +0 -1
  113. data/lib/mongo/operation/write/command/writable.rb +13 -18
  114. data/lib/mongo/operation/write/create_index.rb +4 -27
  115. data/lib/mongo/operation/write/create_user.rb +4 -30
  116. data/lib/mongo/operation/write/delete.rb +6 -29
  117. data/lib/mongo/operation/write/drop_index.rb +3 -3
  118. data/lib/mongo/operation/write/gle.rb +48 -0
  119. data/lib/mongo/operation/write/idable.rb +5 -0
  120. data/lib/mongo/operation/write/insert.rb +2 -24
  121. data/lib/mongo/operation/write/remove_user.rb +4 -27
  122. data/lib/mongo/operation/write/update.rb +13 -36
  123. data/lib/mongo/operation/write/update_user.rb +4 -30
  124. data/lib/mongo/operation/write/write_command_enabled.rb +53 -0
  125. data/lib/mongo/operation/write.rb +2 -0
  126. data/lib/mongo/operation.rb +32 -4
  127. data/lib/mongo/options/mapper.rb +4 -2
  128. data/lib/mongo/options/redacted.rb +156 -0
  129. data/lib/mongo/options.rb +1 -0
  130. data/lib/mongo/protocol/delete.rb +75 -15
  131. data/lib/mongo/protocol/get_more.rb +65 -13
  132. data/lib/mongo/protocol/insert.rb +85 -13
  133. data/lib/mongo/protocol/kill_cursors.rb +59 -14
  134. data/lib/mongo/protocol/message.rb +12 -12
  135. data/lib/mongo/protocol/query.rb +163 -37
  136. data/lib/mongo/protocol/reply.rb +103 -0
  137. data/lib/mongo/protocol/serializers.rb +1 -1
  138. data/lib/mongo/protocol/update.rb +82 -14
  139. data/lib/mongo/retryable.rb +83 -0
  140. data/lib/mongo/server/connectable.rb +21 -25
  141. data/lib/mongo/server/connection.rb +75 -4
  142. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  143. data/lib/mongo/server/connection_pool.rb +12 -0
  144. data/lib/mongo/server/description/features.rb +2 -1
  145. data/lib/mongo/server/description.rb +52 -1
  146. data/lib/mongo/server/monitor/connection.rb +26 -2
  147. data/lib/mongo/server/monitor.rb +19 -3
  148. data/lib/mongo/server.rb +39 -5
  149. data/lib/mongo/server_selector/selectable.rb +40 -31
  150. data/lib/mongo/server_selector.rb +19 -10
  151. data/lib/mongo/socket/ssl.rb +28 -16
  152. data/lib/mongo/socket/tcp.rb +3 -3
  153. data/lib/mongo/socket/unix.rb +5 -8
  154. data/lib/mongo/socket.rb +11 -4
  155. data/lib/mongo/uri.rb +248 -137
  156. data/lib/mongo/version.rb +1 -1
  157. data/lib/mongo.rb +5 -3
  158. data/spec/mongo/address/unix_spec.rb +1 -1
  159. data/spec/mongo/address_spec.rb +25 -0
  160. data/spec/mongo/auth/cr_spec.rb +9 -1
  161. data/spec/mongo/auth/ldap/conversation_spec.rb +43 -0
  162. data/spec/mongo/auth/ldap_spec.rb +9 -1
  163. data/spec/mongo/auth/scram_spec.rb +9 -1
  164. data/spec/mongo/auth/user/view_spec.rb +26 -1
  165. data/spec/mongo/auth/x509_spec.rb +9 -1
  166. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +271 -0
  167. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +239 -0
  168. data/spec/mongo/bulk_write_spec.rb +428 -0
  169. data/spec/mongo/client_spec.rb +167 -17
  170. data/spec/mongo/cluster/topology/replica_set_spec.rb +18 -9
  171. data/spec/mongo/cluster/topology/sharded_spec.rb +11 -3
  172. data/spec/mongo/cluster/topology/single_spec.rb +12 -4
  173. data/spec/mongo/cluster_spec.rb +55 -10
  174. data/spec/mongo/collection/view/aggregation_spec.rb +188 -1
  175. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  176. data/spec/mongo/collection/view/immutable_spec.rb +103 -0
  177. data/spec/mongo/collection/view/map_reduce_spec.rb +99 -4
  178. data/spec/mongo/collection/view/readable_spec.rb +238 -6
  179. data/spec/mongo/collection/view/writable_spec.rb +4 -4
  180. data/spec/mongo/collection/view_spec.rb +459 -71
  181. data/spec/mongo/collection_spec.rb +1291 -9
  182. data/spec/mongo/command_monitoring_spec.rb +51 -0
  183. data/spec/mongo/connection_string_spec.rb +115 -0
  184. data/spec/mongo/crud_spec.rb +2 -2
  185. data/spec/mongo/cursor_spec.rb +3 -3
  186. data/spec/mongo/database_spec.rb +47 -11
  187. data/spec/mongo/dbref_spec.rb +149 -0
  188. data/spec/mongo/grid/file/chunk_spec.rb +5 -5
  189. data/spec/mongo/grid/file/{metadata_spec.rb → info_spec.rb} +29 -17
  190. data/spec/mongo/grid/file_spec.rb +8 -8
  191. data/spec/mongo/grid/fs_bucket_spec.rb +1020 -0
  192. data/spec/mongo/grid/stream/read_spec.rb +275 -0
  193. data/spec/mongo/grid/stream/write_spec.rb +440 -0
  194. data/spec/mongo/grid/stream_spec.rb +48 -0
  195. data/spec/mongo/gridfs_spec.rb +50 -0
  196. data/spec/mongo/logger_spec.rb +0 -40
  197. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +76 -0
  198. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  199. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  200. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  201. data/spec/mongo/monitoring_spec.rb +168 -0
  202. data/spec/mongo/operation/commands/aggregate_spec.rb +69 -0
  203. data/spec/mongo/operation/{read → commands}/collections_info_spec.rb +1 -1
  204. data/spec/mongo/operation/{command_spec.rb → commands/command_spec.rb} +0 -18
  205. data/spec/mongo/operation/{read → commands}/indexes_spec.rb +1 -1
  206. data/spec/mongo/operation/{map_reduce_spec.rb → commands/map_reduce_spec.rb} +1 -19
  207. data/spec/mongo/operation/kill_cursors_spec.rb +1 -17
  208. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  209. data/spec/mongo/operation/read/query_spec.rb +19 -16
  210. data/spec/mongo/operation/{read_preferrable_spec.rb → read_preference_spec.rb} +11 -11
  211. data/spec/mongo/operation/write/bulk/{bulk_delete_spec.rb → delete_spec.rb} +18 -29
  212. data/spec/mongo/operation/write/bulk/{bulk_insert_spec.rb → insert_spec.rb} +3 -14
  213. data/spec/mongo/operation/write/bulk/{bulk_update_spec.rb → update_spec.rb} +8 -19
  214. data/spec/mongo/operation/write/command/delete_spec.rb +0 -16
  215. data/spec/mongo/operation/write/command/insert_spec.rb +0 -16
  216. data/spec/mongo/operation/write/command/update_spec.rb +0 -16
  217. data/spec/mongo/operation/write/delete_spec.rb +4 -4
  218. data/spec/mongo/operation/write/insert_spec.rb +2 -13
  219. data/spec/mongo/operation/write/update_spec.rb +7 -7
  220. data/spec/mongo/options/redacted_spec.rb +350 -0
  221. data/spec/mongo/protocol/kill_cursors_spec.rb +5 -3
  222. data/spec/mongo/protocol/query_spec.rb +15 -30
  223. data/spec/mongo/retryable_spec.rb +147 -0
  224. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  225. data/spec/mongo/server/connection_pool_spec.rb +50 -6
  226. data/spec/mongo/server/connection_spec.rb +49 -4
  227. data/spec/mongo/server/description_spec.rb +49 -3
  228. data/spec/mongo/server/monitor_spec.rb +51 -0
  229. data/spec/mongo/server_discovery_and_monitoring_spec.rb +32 -59
  230. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  231. data/spec/mongo/server_selection_spec.rb +19 -9
  232. data/spec/mongo/server_selector/nearest_spec.rb +35 -27
  233. data/spec/mongo/server_selector/primary_preferred_spec.rb +32 -30
  234. data/spec/mongo/server_selector/primary_spec.rb +21 -14
  235. data/spec/mongo/server_selector/secondary_preferred_spec.rb +28 -26
  236. data/spec/mongo/server_selector/secondary_spec.rb +24 -22
  237. data/spec/mongo/server_selector_spec.rb +87 -24
  238. data/spec/mongo/server_spec.rb +94 -8
  239. data/spec/mongo/socket/ssl_spec.rb +123 -13
  240. data/spec/mongo/socket/unix_spec.rb +52 -0
  241. data/spec/mongo/uri_spec.rb +295 -67
  242. data/spec/spec_helper.rb +40 -24
  243. data/spec/support/authorization.rb +23 -9
  244. data/spec/support/certificates/client.pem +4 -4
  245. data/spec/support/command_monitoring/bulkWrite.yml +73 -0
  246. data/spec/support/command_monitoring/command.yml +42 -0
  247. data/spec/support/command_monitoring/deleteMany.yml +55 -0
  248. data/spec/support/command_monitoring/deleteOne.yml +55 -0
  249. data/spec/support/command_monitoring/find.yml +219 -0
  250. data/spec/support/command_monitoring/insertMany.yml +81 -0
  251. data/spec/support/command_monitoring/insertOne.yml +51 -0
  252. data/spec/support/command_monitoring/updateMany.yml +67 -0
  253. data/spec/support/command_monitoring/updateOne.yml +95 -0
  254. data/spec/support/command_monitoring.rb +365 -0
  255. data/spec/support/connection_string.rb +228 -0
  256. data/spec/support/connection_string_tests/invalid-uris.yml +193 -0
  257. data/spec/support/connection_string_tests/valid-auth.yml +256 -0
  258. data/spec/support/connection_string_tests/valid-host_identifiers.yml +121 -0
  259. data/spec/support/connection_string_tests/valid-options.yml +30 -0
  260. data/spec/support/connection_string_tests/valid-unix_socket-absolute.yml +197 -0
  261. data/spec/support/connection_string_tests/valid-unix_socket-relative.yml +213 -0
  262. data/spec/support/connection_string_tests/valid-warnings.yml +55 -0
  263. data/spec/support/crud/read.rb +22 -19
  264. data/spec/support/crud/write.rb +58 -27
  265. data/spec/support/crud.rb +10 -2
  266. data/spec/support/gridfs.rb +637 -0
  267. data/spec/support/gridfs_tests/delete.yml +157 -0
  268. data/spec/support/gridfs_tests/download.yml +210 -0
  269. data/spec/support/gridfs_tests/download_by_name.yml +113 -0
  270. data/spec/support/gridfs_tests/upload.yml +158 -0
  271. data/spec/support/matchers.rb +1 -1
  272. data/spec/support/sdam/rs/equal_electionids.yml +44 -0
  273. data/spec/support/sdam/rs/new_primary_new_electionid.yml +95 -0
  274. data/spec/support/sdam/rs/null_election_id.yml +144 -0
  275. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +124 -0
  276. data/spec/support/sdam/rs/primary_mismatched_me.yml +37 -0
  277. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +75 -0
  278. data/spec/support/sdam/rs/secondary_mismatched_me.yml +37 -0
  279. data/spec/support/sdam/sharded/mongos_disconnect.yml +104 -0
  280. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  281. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  282. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  283. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  284. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  285. data/spec/support/sdam/single/not_ok_response.yml +0 -1
  286. data/spec/support/server_discovery_and_monitoring.rb +22 -3
  287. data/spec/support/server_selection.rb +3 -1
  288. data/spec/support/shared/bulk_write.rb +218 -22
  289. data/spec/support/shared/server_selector.rb +80 -14
  290. data.tar.gz.sig +0 -0
  291. metadata +188 -59
  292. metadata.gz.sig +0 -0
  293. data/lib/mongo/bulk_write/bulk_writable.rb +0 -196
  294. data/lib/mongo/bulk_write/deletable.rb +0 -56
  295. data/lib/mongo/bulk_write/insertable.rb +0 -48
  296. data/lib/mongo/bulk_write/replacable.rb +0 -57
  297. data/lib/mongo/bulk_write/updatable.rb +0 -68
  298. data/lib/mongo/grid/fs.rb +0 -149
  299. data/lib/mongo/operation/list_collections/result.rb +0 -114
  300. data/lib/mongo/operation/list_indexes/result.rb +0 -118
  301. data/lib/mongo/operation/read/collections_info.rb +0 -68
  302. data/lib/mongo/operation/read/indexes.rb +0 -69
  303. data/lib/mongo/operation/read/list_collections.rb +0 -76
  304. data/lib/mongo/operation/read/list_indexes.rb +0 -78
  305. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +0 -75
  306. data/lib/mongo/operation/write/bulk/bulk_delete.rb +0 -145
  307. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +0 -130
  308. data/lib/mongo/operation/write/bulk/bulk_insert.rb +0 -132
  309. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +0 -67
  310. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +0 -162
  311. data/lib/mongo/operation/write/bulk/bulk_update.rb +0 -154
  312. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +0 -83
  313. data/spec/mongo/bulk/bulk_write_spec.rb +0 -262
  314. data/spec/mongo/grid/fs_spec.rb +0 -160
  315. data/spec/mongo/loggable_spec.rb +0 -63
  316. data/spec/mongo/operation/aggregate_spec.rb +0 -127
  317. /data/lib/mongo/operation/{aggregate → commands/aggregate}/result.rb +0 -0
data/lib/mongo/cluster.rb CHANGED
@@ -65,9 +65,9 @@ module Mongo
65
65
  address = Address.new(host)
66
66
  if !addresses.include?(address)
67
67
  if addition_allowed?(address)
68
- log_debug([ "Adding #{address.to_s} to the cluster." ])
68
+ log_debug("Adding #{address.to_s} to the cluster.")
69
69
  @update_lock.synchronize { @addresses.push(address) }
70
- server = Server.new(address, self, event_listeners, options)
70
+ server = Server.new(address, self, @monitoring, event_listeners, options)
71
71
  @update_lock.synchronize { @servers.push(server) }
72
72
  server
73
73
  end
@@ -76,16 +76,22 @@ module Mongo
76
76
 
77
77
  # Instantiate the new cluster.
78
78
  #
79
+ # @api private
80
+ #
79
81
  # @example Instantiate the cluster.
80
- # Mongo::Cluster.new(["127.0.0.1:27017"])
82
+ # Mongo::Cluster.new(["127.0.0.1:27017"], monitoring)
83
+ #
84
+ # @note Cluster should never be directly instantiated outside of a Client.
81
85
  #
82
86
  # @param [ Array<String> ] seeds The addresses of the configured servers.
87
+ # @param [ Monitoring ] monitoring The monitoring.
83
88
  # @param [ Hash ] options The options.
84
89
  #
85
90
  # @since 2.0.0
86
- def initialize(seeds, options = {})
91
+ def initialize(seeds, monitoring, options = Options::Redacted.new)
87
92
  @addresses = []
88
93
  @servers = []
94
+ @monitoring = monitoring
89
95
  @event_listeners = Event::Listeners.new
90
96
  @options = options.freeze
91
97
  @topology = Topology.initial(seeds, options)
@@ -119,7 +125,7 @@ module Mongo
119
125
  #
120
126
  # @since 2.0.0
121
127
  def next_primary
122
- ServerSelector.get({ mode: :primary }, options).select_server(self)
128
+ ServerSelector.get(ServerSelector::PRIMARY.merge(options)).select_server(self)
123
129
  end
124
130
 
125
131
  # Elect a primary server from the description that has just changed to a
@@ -160,7 +166,7 @@ module Mongo
160
166
  #
161
167
  # @since 2.0.0
162
168
  def remove(host)
163
- log_debug([ "#{host} being removed from the cluster." ])
169
+ log_debug("#{host} being removed from the cluster.")
164
170
  address = Address.new(host)
165
171
  removed_servers = @servers.select { |s| s.address == address }
166
172
  @update_lock.synchronize { @servers = @servers - removed_servers }
@@ -196,6 +202,31 @@ module Mongo
196
202
  topology.servers(servers_list.compact).compact
197
203
  end
198
204
 
205
+ # Disconnect all servers.
206
+ #
207
+ # @example Disconnect the cluster's servers.
208
+ # cluster.disconnect!
209
+ #
210
+ # @return [ true ] Always true.
211
+ #
212
+ # @since 2.1.0
213
+ def disconnect!
214
+ @servers.each { |server| server.disconnect! } and true
215
+ end
216
+
217
+ # Reconnect all servers.
218
+ #
219
+ # @example Reconnect the cluster's servers.
220
+ # cluster.reconnect!
221
+ #
222
+ # @return [ true ] Always true.
223
+ #
224
+ # @since 2.1.0
225
+ def reconnect!
226
+ scan!
227
+ servers.each { |server| server.reconnect! } and true
228
+ end
229
+
199
230
  # Add hosts in a description to the cluster.
200
231
  #
201
232
  # @example Add hosts in a description to the cluster.
@@ -240,7 +271,11 @@ module Mongo
240
271
  #
241
272
  # @since 2.0.0
242
273
  def self.create(client)
243
- cluster = Cluster.new(client.cluster.addresses.map(&:to_s), client.options)
274
+ cluster = Cluster.new(
275
+ client.cluster.addresses.map(&:to_s),
276
+ client.instance_variable_get(:@monitoring).dup,
277
+ client.options
278
+ )
244
279
  client.instance_variable_set(:@cluster, cluster)
245
280
  end
246
281
 
@@ -25,6 +25,8 @@ module Mongo
25
25
  include Immutable
26
26
  include Iterable
27
27
  include Explainable
28
+ include Loggable
29
+ include Retryable
28
30
 
29
31
  # @return [ View ] view The collection view.
30
32
  attr_reader :view
@@ -37,6 +39,20 @@ module Mongo
37
39
  # Delegate necessary operations to the collection.
38
40
  def_delegators :collection, :database
39
41
 
42
+ # Options mapping for an aggregation.
43
+ #
44
+ # @since 2.1.0
45
+ OPTIONS_MAP = {
46
+ :allow_disk_use => :allowDiskUse,
47
+ :max_time_ms => :maxTimeMS,
48
+ :explain => :explain
49
+ }.freeze
50
+
51
+ # The reroute message.
52
+ #
53
+ # @since 2.1.0
54
+ REROUTE = 'Rerouting the Aggregation operation to the primary server.'.freeze
55
+
40
56
  # Set to true if disk usage is allowed during the aggregation.
41
57
  #
42
58
  # @example Set disk usage flag.
@@ -49,7 +65,7 @@ module Mongo
49
65
  #
50
66
  # @since 2.0.0
51
67
  def allow_disk_use(value = nil)
52
- configure(:allowDiskUse, value)
68
+ configure(__method__, value)
53
69
  end
54
70
 
55
71
  # Initialize the aggregation for the provided collection view, pipeline
@@ -89,11 +105,28 @@ module Mongo
89
105
  :selector => {
90
106
  :aggregate => collection.name,
91
107
  :pipeline => pipeline,
92
- :cursor => view.batch_size ? { :batchSize => view.batch_size } : {}
93
- }.merge!(options)
108
+ :cursor => cursor,
109
+ }.merge!(agg_options)
94
110
  }
95
111
  end
96
112
 
113
+ def agg_options
114
+ @agg_options ||= options.each.reduce({}) do |opts, (key, value)|
115
+ OPTIONS_MAP[key] ? opts.merge!(OPTIONS_MAP[key] => value) : opts
116
+ end
117
+ end
118
+
119
+ def cursor
120
+ if options[:use_cursor] == true || options[:use_cursor].nil?
121
+ batch_size_doc
122
+ end
123
+ end
124
+
125
+ def batch_size_doc
126
+ (value = options[:batch_size] || view.batch_size) ?
127
+ { :batchSize => value } : {}
128
+ end
129
+
97
130
  def explain_options
98
131
  { :explain => true }
99
132
  end
@@ -106,14 +139,20 @@ module Mongo
106
139
  Operation::Aggregate.new(aggregate_spec)
107
140
  end
108
141
 
142
+ def valid_server?(server)
143
+ server.standalone? || server.mongos? || server.primary? || secondary_ok?
144
+ end
145
+
146
+ def secondary_ok?
147
+ pipeline.none? { |op| op.key?('$out') || op.key?(:$out) }
148
+ end
149
+
109
150
  def send_initial_query(server)
110
- begin
111
- initial_query_op.execute(server.context)
112
- rescue Mongo::Error::NeedPrimaryServer
113
- warn 'Rerouting the Aggregation operation to the primary server.'
114
- server = ServerSelector.get(mode: :primary).select_server(cluster)
115
- initial_query_op.execute(server.context)
151
+ unless valid_server?(server)
152
+ log_warn(REROUTE)
153
+ server = cluster.next_primary
116
154
  end
155
+ initial_query_op.execute(server.context)
117
156
  end
118
157
  end
119
158
  end
@@ -22,14 +22,14 @@ module Mongo
22
22
 
23
23
  private
24
24
 
25
- # @api private
26
- #
27
- # @note In the including class, the method #immutable needs to be
28
- # implemented in order to define how a new class of that type needs to
29
- # be instantiated.
30
25
  def configure(field, value)
31
26
  return options[field] if value.nil?
32
- new(options.merge(field => value))
27
+ new(options.merge(field => value, :modifiers => @modifiers))
28
+ end
29
+
30
+ def configure_modifier(field, value)
31
+ return @modifiers[Readable::SPECIAL_FIELDS[field]] if value.nil?
32
+ new(options.merge(:modifiers => @modifiers.merge(Readable::SPECIAL_FIELDS[field] => value)))
33
33
  end
34
34
 
35
35
  def configure_flag(flag)
@@ -35,12 +35,26 @@ module Mongo
35
35
  #
36
36
  # @yieldparam [ Hash ] Each matching document.
37
37
  def each
38
- server = read.select_server(cluster)
39
- cursor = Cursor.new(view, send_initial_query(server), server).to_enum
40
- cursor.each do |doc|
38
+ @cursor = nil
39
+ read_with_retry do
40
+ server = read.select_server(cluster)
41
+ result = send_initial_query(server)
42
+ @cursor = Cursor.new(view, result, server)
43
+ end
44
+ @cursor.each do |doc|
41
45
  yield doc
42
46
  end if block_given?
43
- cursor
47
+ @cursor.to_enum
48
+ end
49
+
50
+ # Stop the iteration by sending a KillCursors command to the server.
51
+ #
52
+ # @example Stop the iteration.
53
+ # view.close_query
54
+ #
55
+ # @since 2.1.0
56
+ def close_query
57
+ @cursor.send(:kill_cursors) if @cursor
44
58
  end
45
59
  end
46
60
  end
@@ -24,7 +24,18 @@ module Mongo
24
24
  extend Forwardable
25
25
  include Enumerable
26
26
  include Immutable
27
- include Iterable
27
+ include Loggable
28
+ include Retryable
29
+
30
+ # The inline option.
31
+ #
32
+ # @since 2.1.0
33
+ INLINE = 'inline'.freeze
34
+
35
+ # Reroute message.
36
+ #
37
+ # @since 2.1.0
38
+ REROUTE = 'Rerouting the MapReduce operation to the primary server.'.freeze
28
39
 
29
40
  # @return [ View ] view The collection view.
30
41
  attr_reader :view
@@ -41,6 +52,31 @@ module Mongo
41
52
  # Delegate necessary operations to the collection.
42
53
  def_delegators :collection, :database
43
54
 
55
+ # Iterate through documents returned by the map/reduce.
56
+ #
57
+ # @example Iterate through the result of the map/reduce.
58
+ # map_reduce.each do |document|
59
+ # p document
60
+ # end
61
+ #
62
+ # @return [ Enumerator ] The enumerator.
63
+ #
64
+ # @since 2.0.0
65
+ #
66
+ # @yieldparam [ Hash ] Each matching document.
67
+ def each
68
+ @cursor = nil
69
+ write_with_retry do
70
+ server = read.select_server(cluster)
71
+ result = send_initial_query(server)
72
+ @cursor = Cursor.new(view, result, server)
73
+ end
74
+ @cursor.each do |doc|
75
+ yield doc
76
+ end if block_given?
77
+ @cursor.to_enum
78
+ end
79
+
44
80
  # Set or get the finalize function for the operation.
45
81
  #
46
82
  # @example Set the finalize function.
@@ -147,7 +183,7 @@ module Mongo
147
183
  private
148
184
 
149
185
  def inline?
150
- out.nil? || out == { inline: 1 } || out == { 'inline' => 1 }
186
+ out.nil? || out == { inline: 1 } || out == { INLINE => 1 }
151
187
  end
152
188
 
153
189
  def map_reduce_spec
@@ -158,12 +194,16 @@ module Mongo
158
194
  :mapreduce => collection.name,
159
195
  :map => map,
160
196
  :reduce => reduce,
161
- :query => view.selector[:$query] || view.selector,
197
+ :query => view.modifiers[:$query] || view.selector,
162
198
  :out => { inline: 1 }
163
- }.merge(options).merge(view.options)
199
+ }.merge(options).merge(view_options)
164
200
  }
165
201
  end
166
202
 
203
+ def view_options
204
+ view.sort ? view.options.merge(:sort => view.sort) : view.options
205
+ end
206
+
167
207
  def new(options)
168
208
  MapReduce.new(view, map, reduce, options)
169
209
  end
@@ -172,27 +212,28 @@ module Mongo
172
212
  Operation::MapReduce.new(map_reduce_spec)
173
213
  end
174
214
 
215
+ def valid_server?(server)
216
+ server.standalone? || server.mongos? || server.primary? || secondary_ok?
217
+ end
218
+
219
+ def secondary_ok?
220
+ out.respond_to?(:keys) && out.keys.first.to_s.downcase == INLINE
221
+ end
222
+
175
223
  def send_initial_query(server)
176
- result =
177
- begin
178
- initial_query_op.execute(server.context)
179
- rescue Mongo::Error::NeedPrimaryServer
180
- warn 'Rerouting the MapReduce operation to the primary server.'
181
- server = ServerSelector.get(mode: :primary).select_server(cluster)
182
- initial_query_op.execute(server.context)
183
- end
184
- if inline?
185
- result
186
- else
187
- send_fetch_query(server)
224
+ unless valid_server?(server)
225
+ log_warn(REROUTE)
226
+ server = cluster.next_primary
188
227
  end
228
+ result = initial_query_op.execute(server.context)
229
+ inline? ? result : send_fetch_query(server)
189
230
  end
190
231
 
191
232
  def fetch_query_spec
192
233
  { :selector => {},
193
234
  :options => {},
194
235
  :db_name => database.name,
195
- :coll_name => out.values.first }
236
+ :coll_name => out.respond_to?(:keys) ? out.values.first : out }
196
237
  end
197
238
 
198
239
  def fetch_query_op
@@ -21,19 +21,32 @@ module Mongo
21
21
  # @since 2.0.0
22
22
  module Readable
23
23
 
24
- # Special fields and their getters for the query selector.
24
+ # Special fields and their option names for the query selector.
25
25
  #
26
26
  # @since 2.0.0
27
27
  SPECIAL_FIELDS = {
28
- :$query => :selector,
29
- :$readPreference => :read_pref_formatted,
30
- :$orderby => :sort,
31
- :$hint => :hint,
32
- :$comment => :comment,
33
- :$snapshot => :snapshot,
34
- :$maxScan => :max_scan,
35
- :$showDiskLoc => :show_disk_loc,
36
- :$explain => :explained?
28
+ :sort => :$orderby,
29
+ :hint => :$hint,
30
+ :comment => :$comment,
31
+ :snapshot => :$snapshot,
32
+ :max_scan => :$maxScan,
33
+ :max_value => :$max,
34
+ :min_value => :$min,
35
+ :max_time_ms => :$maxTimeMS,
36
+ :return_key => :$returnKey,
37
+ :show_disk_loc => :$showDiskLoc,
38
+ :explain => :$explain
39
+ }.freeze
40
+
41
+ # Options to cursor flags mapping.
42
+ #
43
+ # @since 2.1.0
44
+ CURSOR_FLAGS_MAP = {
45
+ :allow_partial_results => [ :partial ],
46
+ :oplog_replay => [ :oplog_replay ],
47
+ :no_cursor_timeout => [ :no_cursor_timeout ],
48
+ :tailable => [ :tailable_cursor ],
49
+ :tailable_await => [ :await_data, :tailable_cursor]
37
50
  }.freeze
38
51
 
39
52
  # Execute an aggregation on the collection view.
@@ -97,7 +110,7 @@ module Mongo
97
110
  #
98
111
  # @since 2.0.0
99
112
  def comment(comment = nil)
100
- configure(:comment, comment)
113
+ configure_modifier(:comment, comment)
101
114
  end
102
115
 
103
116
  # Get a count of matching documents in the collection.
@@ -111,6 +124,8 @@ module Mongo
111
124
  # @option options :hint [ Hash ] Override default index selection and force
112
125
  # MongoDB to use a specific index for the query.
113
126
  # @option options :limit [ Integer ] Max number of docs to return.
127
+ # @option options :max_time_ms [ Integer ] The maximum amount of time to allow the
128
+ # command to run.
114
129
  # @option options :read [ Hash ] The read preference for this command.
115
130
  #
116
131
  # @return [ Integer ] The document count.
@@ -121,7 +136,10 @@ module Mongo
121
136
  cmd[:skip] = options[:skip] if options[:skip]
122
137
  cmd[:hint] = options[:hint] if options[:hint]
123
138
  cmd[:limit] = options[:limit] if options[:limit]
124
- database.command(cmd, options).n
139
+ cmd[:maxTimeMS] = options[:max_time_ms] if options[:max_time_ms]
140
+ read_with_retry do
141
+ database.command(cmd, options).n
142
+ end
125
143
  end
126
144
 
127
145
  # Get a list of distinct values for a specific field.
@@ -132,18 +150,21 @@ module Mongo
132
150
  # @param [ String, Symbol ] field_name The name of the field.
133
151
  # @param [ Hash ] options Options for the distinct command.
134
152
  #
153
+ # @option options :max_time_ms [ Integer ] The maximum amount of time to allow the
154
+ # command to run.
135
155
  # @option options :read [ Hash ] The read preference for this command.
136
156
  #
137
157
  # @return [ Array<Object> ] The list of distinct values.
138
158
  #
139
159
  # @since 2.0.0
140
160
  def distinct(field_name, options={})
141
- database.command({
142
- :distinct => collection.name,
143
- :key => field_name.to_s,
144
- :query => selector },
145
- options
146
- ).documents.first['values']
161
+ cmd = { :distinct => collection.name,
162
+ :key => field_name.to_s,
163
+ :query => selector }
164
+ cmd[:maxTimeMS] = options[:max_time_ms] if options[:max_time_ms]
165
+ read_with_retry do
166
+ database.command(cmd, options).first['values']
167
+ end
147
168
  end
148
169
 
149
170
  # The index that MongoDB will be forced to use for the query.
@@ -157,7 +178,7 @@ module Mongo
157
178
  #
158
179
  # @since 2.0.0
159
180
  def hint(hint = nil)
160
- configure(:hint, hint)
181
+ configure_modifier(:hint, hint)
161
182
  end
162
183
 
163
184
  # The max number of docs to return from the query.
@@ -201,7 +222,35 @@ module Mongo
201
222
  #
202
223
  # @since 2.0.0
203
224
  def max_scan(value = nil)
204
- configure(:max_scan, value)
225
+ configure_modifier(:max_scan, value)
226
+ end
227
+
228
+ # Set the maximum value to search.
229
+ #
230
+ # @example Set the max value.
231
+ # view.max_value(_id: 1)
232
+ #
233
+ # @param [ Hash ] value The max field and value.
234
+ #
235
+ # @return [ Hash, View ] The value or a new +View+.
236
+ #
237
+ # @since 2.1.0
238
+ def max_value(value = nil)
239
+ configure_modifier(:max_value, value)
240
+ end
241
+
242
+ # Set the minimum value to search.
243
+ #
244
+ # @example Set the min value.
245
+ # view.min_value(_id: 1)
246
+ #
247
+ # @param [ Hash ] value The min field and value.
248
+ #
249
+ # @return [ Hash, View ] The value or a new +View+.
250
+ #
251
+ # @since 2.1.0
252
+ def min_value(value = nil)
253
+ configure_modifier(:min_value, value)
205
254
  end
206
255
 
207
256
  # The server normally times out idle cursors after an inactivity period
@@ -249,7 +298,22 @@ module Mongo
249
298
  # @since 2.0.0
250
299
  def read(value = nil)
251
300
  return default_read if value.nil?
252
- configure(:read, value)
301
+ selector = value.is_a?(Hash) ? ServerSelector.get(client.options.merge(value)) : value
302
+ configure(:read, selector)
303
+ end
304
+
305
+ # Set whether to return only the indexed field or fields.
306
+ #
307
+ # @example Set the return key value.
308
+ # view.return_key(true)
309
+ #
310
+ # @param [ true, false ] value The return key value.
311
+ #
312
+ # @return [ true, false, View ] The value or a new +View+.
313
+ #
314
+ # @since 2.1.0
315
+ def return_key(value = nil)
316
+ configure_modifier(:return_key, value)
253
317
  end
254
318
 
255
319
  # Set whether the disk location should be shown for each document.
@@ -264,7 +328,7 @@ module Mongo
264
328
  #
265
329
  # @since 2.0.0
266
330
  def show_disk_loc(value = nil)
267
- configure(:show_disk_loc, value)
331
+ configure_modifier(:show_disk_loc, value)
268
332
  end
269
333
 
270
334
  # The number of docs to skip before returning results.
@@ -294,7 +358,7 @@ module Mongo
294
358
  #
295
359
  # @since 2.0.0
296
360
  def snapshot(value = nil)
297
- configure(:snapshot, value)
361
+ configure_modifier(:snapshot, value)
298
362
  end
299
363
 
300
364
  # The key and direction pairs by which the result set will be sorted.
@@ -309,33 +373,106 @@ module Mongo
309
373
  #
310
374
  # @since 2.0.0
311
375
  def sort(spec = nil)
312
- configure(:sort, spec)
376
+ configure_modifier(:sort, spec)
377
+ end
378
+
379
+ # “meta” operators that let you modify the output or behavior of a query.
380
+ #
381
+ # @example Set the modifiers document.
382
+ # view.modifiers(:$orderby => Mongo::Index::ASCENDING)
383
+ #
384
+ # @param [ Hash ] doc The modifiers document.
385
+ #
386
+ # @return [ Hash, View ] Either the modifiers document or a new +View+.
387
+ #
388
+ # @since 2.1.0
389
+ def modifiers(doc = nil)
390
+ return @modifiers if doc.nil?
391
+ new(options.merge(:modifiers => doc))
392
+ end
393
+
394
+ # A cumulative time limit in milliseconds for processing operations on a cursor.
395
+ #
396
+ # @example Set the max time ms value.
397
+ # view.max_time_ms(500)
398
+ #
399
+ # @param [ Integer ] max The max time in milliseconds.
400
+ #
401
+ # @return [ Integer, View ] Either the max time ms value or a new +View+.
402
+ #
403
+ # @since 2.1.0
404
+ def max_time_ms(max = nil)
405
+ configure_modifier(:max_time_ms, max)
313
406
  end
314
407
 
315
408
  private
316
409
 
317
- def default_read(read = nil)
410
+ def default_read
318
411
  options[:read] || read_preference
319
412
  end
320
413
 
321
414
  def flags
322
- @flags ||= (!primary? ? [ :slave_ok ] : [])
415
+ @flags ||= CURSOR_FLAGS_MAP.each.reduce([]) do |flags, (key, value)|
416
+ if options[key] || (options[:cursor_type] && options[:cursor_type] == key)
417
+ flags.push(*value)
418
+ end
419
+ flags
420
+ end
323
421
  end
324
422
 
325
- def has_special_fields?
326
- sort || hint || comment || max_scan || show_disk_loc || snapshot || explained? || cluster.sharded?
423
+ def parallel_scan(cursor_count)
424
+ server = read.select_server(cluster)
425
+ Operation::ParallelScan.new(
426
+ :coll_name => collection.name,
427
+ :db_name => database.name,
428
+ :cursor_count => cursor_count
429
+ ).execute(server.context).cursor_ids.map do |cursor_id|
430
+ result = Operation::Read::GetMore.new({ :to_return => 0,
431
+ :cursor_id => cursor_id,
432
+ :db_name => database.name,
433
+ :coll_name => collection.name
434
+ }).execute(server.context)
435
+ Cursor.new(self, result, server)
436
+ end
437
+ end
438
+
439
+ def setup(sel, opts)
440
+ setup_options(opts)
441
+ setup_selector(sel)
327
442
  end
328
443
 
329
- def primary?
330
- read.name == :primary
444
+ def setup_options(opts)
445
+ @options = opts ? opts.dup : {}
446
+ @modifiers = @options[:modifiers] ? @options.delete(:modifiers).dup : BSON::Document.new
447
+ @options.keys.each { |k| @modifiers.merge!(SPECIAL_FIELDS[k] => @options.delete(k)) if SPECIAL_FIELDS[k] }
448
+ @options.freeze
449
+ end
450
+
451
+ def setup_selector(sel)
452
+ @selector = sel ? sel.dup : {}
453
+ if @selector[:$query] || @selector['$query']
454
+ @selector.keys.each { |k| @modifiers.merge!(k => @selector.delete(k)) if k[0] == '$' }
455
+ end
456
+ @modifiers.freeze
457
+ @selector.freeze
331
458
  end
332
459
 
333
460
  def query_options
334
- { :project => projection, :skip => skip, :limit => to_return, :flags => flags }
461
+ {
462
+ :project => projection,
463
+ :skip => skip,
464
+ :limit => limit,
465
+ :flags => flags,
466
+ :batch_size => batch_size
467
+ }
468
+ end
469
+
470
+ def requires_special_selector?
471
+ !modifiers.empty? || cluster.sharded?
335
472
  end
336
473
 
337
474
  def query_spec
338
- sel = has_special_fields? ? special_selector : selector
475
+ sel = requires_special_selector? ? special_selector : selector
339
476
  { :selector => sel,
340
477
  :read => read,
341
478
  :options => query_options,
@@ -344,19 +481,13 @@ module Mongo
344
481
  end
345
482
 
346
483
  def read_pref_formatted
347
- read.to_mongos
484
+ @read_formatted ||= read.to_mongos
348
485
  end
349
486
 
350
487
  def special_selector
351
- SPECIAL_FIELDS.reduce({}) do |hash, (key, method)|
352
- value = send(method)
353
- hash[key] = value if value
354
- hash
355
- end
356
- end
357
-
358
- def to_return
359
- [ limit || batch_size, batch_size || limit ].min
488
+ sel = BSON::Document.new(:$query => selector).merge!(modifiers)
489
+ sel[:$readPreference] = read_pref_formatted unless read_pref_formatted.nil?
490
+ sel
360
491
  end
361
492
 
362
493
  def validate_doc!(doc)