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
@@ -0,0 +1,132 @@
1
+ # Copyright (C) 2015 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
+ class BulkWrite
17
+
18
+ # Defines behaviour around transformations.
19
+ #
20
+ # @api private
21
+ #
22
+ # @since 2.1.0
23
+ module Transformable
24
+
25
+ # The delete many model constant.
26
+ #
27
+ # @since 2.1.0
28
+ DELETE_MANY = :delete_many.freeze
29
+
30
+ # The delete one model constant.
31
+ #
32
+ # @since 2.1.0
33
+ DELETE_ONE = :delete_one.freeze
34
+
35
+ # The insert one model constant.
36
+ #
37
+ # @since 2.1.0
38
+ INSERT_ONE = :insert_one.freeze
39
+
40
+ # The replace one model constant.
41
+ #
42
+ # @since 2.1.0
43
+ REPLACE_ONE = :replace_one.freeze
44
+
45
+ # The update many model constant.
46
+ #
47
+ # @since 2.1.0
48
+ UPDATE_MANY = :update_many.freeze
49
+
50
+ # The update one model constant.
51
+ #
52
+ # @since 2.1.0
53
+ UPDATE_ONE = :update_one.freeze
54
+
55
+ # Proc to transform delete many ops.
56
+ #
57
+ # @since 2.1.0
58
+ DELETE_MANY_TRANSFORM = ->(doc){
59
+ { Operation::Q => doc[:filter], Operation::LIMIT => 0 }
60
+ }
61
+
62
+ # Proc to transform delete one ops.
63
+ #
64
+ # @since 2.1.0
65
+ DELETE_ONE_TRANSFORM = ->(doc){
66
+ { Operation::Q => doc[:filter], Operation::LIMIT => 1 }
67
+ }
68
+
69
+ # Proc to transform insert one ops.
70
+ #
71
+ # @since 2.1.0
72
+ INSERT_ONE_TRANSFORM = ->(doc){
73
+ doc
74
+ }
75
+
76
+ # Proc to transfor replace one ops.
77
+ #
78
+ # @since 2.1.0
79
+ REPLACE_ONE_TRANSFORM = ->(doc){
80
+ {
81
+ Operation::Q => doc[:filter],
82
+ Operation::U => doc[:replacement],
83
+ Operation::MULTI => false,
84
+ Operation::UPSERT => doc.fetch(:upsert, false)
85
+ }
86
+ }
87
+
88
+ # Proc to transform update many ops.
89
+ #
90
+ # @since 2.1.0
91
+ UPDATE_MANY_TRANSFORM = ->(doc){
92
+ {
93
+ Operation::Q => doc[:filter],
94
+ Operation::U => doc[:update],
95
+ Operation::MULTI => true,
96
+ Operation::UPSERT => doc.fetch(:upsert, false)
97
+ }
98
+ }
99
+
100
+ # Proc to transform update one ops.
101
+ #
102
+ # @since 2.1.0
103
+ UPDATE_ONE_TRANSFORM = ->(doc){
104
+ {
105
+ Operation::Q => doc[:filter],
106
+ Operation::U => doc[:update],
107
+ Operation::MULTI => false,
108
+ Operation::UPSERT => doc.fetch(:upsert, false)
109
+ }
110
+ }
111
+
112
+ # Document mappers from the bulk api input into proper commands.
113
+ #
114
+ # @since 2.1.0
115
+ MAPPERS = {
116
+ DELETE_MANY => DELETE_MANY_TRANSFORM,
117
+ DELETE_ONE => DELETE_ONE_TRANSFORM,
118
+ INSERT_ONE => INSERT_ONE_TRANSFORM,
119
+ REPLACE_ONE => REPLACE_ONE_TRANSFORM,
120
+ UPDATE_MANY => UPDATE_MANY_TRANSFORM,
121
+ UPDATE_ONE => UPDATE_ONE_TRANSFORM
122
+ }.freeze
123
+
124
+ private
125
+
126
+ def transform(name, document)
127
+ validate(name, document)
128
+ MAPPERS[name].call(document)
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2015 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
+ class BulkWrite
17
+
18
+ # Combines groups of bulk write operations in no order.
19
+ #
20
+ # @api private
21
+ #
22
+ # @since 2.1.0
23
+ class UnorderedCombiner
24
+ include Transformable
25
+ include Validatable
26
+ include Combineable
27
+
28
+ # Combine the requests in order.
29
+ #
30
+ # @api private
31
+ #
32
+ # @example Combine the requests.
33
+ # combiner.combine
34
+ #
35
+ # @return [ Array<Hash> ] The combined requests.
36
+ #
37
+ # @since 2.1.0
38
+ def combine
39
+ combine_requests({}).map do |name, ops|
40
+ { name => ops }
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def add(operations, name, document)
47
+ (operations[name] ||= []).push(transform(name, document))
48
+ operations
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,62 @@
1
+ # Copyright (C) 2015 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
+ class BulkWrite
17
+
18
+ # Defines behaviour around validations.
19
+ #
20
+ # @api private
21
+ #
22
+ # @since 2.1.0
23
+ module Validatable
24
+
25
+ # Validate the document.
26
+ #
27
+ # @api private
28
+ #
29
+ # @example Validate the document.
30
+ # validatable.validate(:insert_one, { _id: 0 })
31
+ #
32
+ # @param [ Symbol ] name The operation name.
33
+ # @param [ Hash, BSON::Document ] document The document.
34
+ #
35
+ # @raise [ InvalidBulkOperation ] If not valid.
36
+ #
37
+ # @return [ Hash, BSON::Document ] The document.
38
+ #
39
+ # @since 2.1.0
40
+ def validate(name, document)
41
+ validate_operation(name)
42
+ validate_document(name, document)
43
+ end
44
+
45
+ private
46
+
47
+ def validate_document(name, document)
48
+ if document.respond_to?(:keys) || document.respond_to?(:data)
49
+ document
50
+ else
51
+ raise Error::InvalidBulkOperation.new(name, document)
52
+ end
53
+ end
54
+
55
+ def validate_operation(name)
56
+ unless Transformable::MAPPERS.key?(name)
57
+ raise Error::InvalidBulkOperationType.new(name)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -12,41 +12,177 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'mongo/bulk_write/bulk_writable'
16
- require 'mongo/bulk_write/ordered_bulk_write'
17
- require 'mongo/bulk_write/unordered_bulk_write'
15
+ require 'mongo/bulk_write/result'
16
+ require 'mongo/bulk_write/transformable'
17
+ require 'mongo/bulk_write/validatable'
18
+ require 'mongo/bulk_write/combineable'
19
+ require 'mongo/bulk_write/ordered_combiner'
20
+ require 'mongo/bulk_write/unordered_combiner'
21
+ require 'mongo/bulk_write/result_combiner'
18
22
 
19
23
  module Mongo
20
- module BulkWrite
21
- extend self
24
+ class BulkWrite
25
+ extend Forwardable
26
+ include Retryable
22
27
 
23
- # Get a bulk write object either of type ordered or unordered.
28
+ # @return [ Mongo::Collection ] collection The collection.
29
+ attr_reader :collection
30
+
31
+ # @return [ Array<Hash, BSON::Document> ] requests The requests.
32
+ attr_reader :requests
33
+
34
+ # @return [ Hash, BSON::Document ] options The options.
35
+ attr_reader :options
36
+
37
+ # Delegate various methods to the collection.
38
+ def_delegators :@collection, :database, :cluster, :next_primary
39
+
40
+ # Execute the bulk write operation.
41
+ #
42
+ # @example Execute the bulk write.
43
+ # bulk_write.execute
44
+ #
45
+ # @return [ Mongo::BulkWrite::Result ] The result.
46
+ #
47
+ # @since 2.1.0
48
+ def execute
49
+ operation_id = Monitoring.next_operation_id
50
+ result_combiner = ResultCombiner.new
51
+ write_with_retry do
52
+ server = next_primary
53
+ operations.each do |operation|
54
+ execute_operation(
55
+ operation.keys.first,
56
+ operation.values.first,
57
+ server,
58
+ operation_id,
59
+ result_combiner
60
+ )
61
+ end
62
+ end
63
+ result_combiner.result
64
+ end
65
+
66
+ # Create the new bulk write operation.
24
67
  #
25
- # @example Get a bulk write object.
26
- # Mongo::BulkWrite.get(collection, operations, ordered: true)
68
+ # @api private
27
69
  #
28
- # @param [ Collection ] collection The collection on which the operations
29
- # will be executed.
70
+ # @example Create an ordered bulk write.
71
+ # Mongo::BulkWrite.new(collection, [{ insert_one: { _id: 1 }}])
30
72
  #
31
- # @param [ Array<Hash> ] operations The operations to execute.
73
+ # @example Create an unordered bulk write.
74
+ # Mongo::BulkWrite.new(collection, [{ insert_one: { _id: 1 }}], ordered: false)
32
75
  #
33
- # @param [ Hash ] options The options for the bulk write object.
76
+ # @example Create an ordered mixed bulk write.
77
+ # Mongo::BulkWrite.new(
78
+ # collection,
79
+ # [
80
+ # { insert_one: { _id: 1 }},
81
+ # { update_one: { filter: { _id: 0 }, update: { '$set' => { name: 'test' }}}},
82
+ # { delete_one: { filter: { _id: 2 }}}
83
+ # ]
84
+ # )
85
+ #
86
+ # @param [ Mongo::Collection ] collection The collection.
87
+ # @param [ Array<Hash, BSON::Document> ] requests The requests.
88
+ # @param [ Hash, BSON::Document ] options The options.
89
+ #
90
+ # @since 2.1.0
91
+ def initialize(collection, requests, options = {})
92
+ @collection = collection
93
+ @requests = requests
94
+ @options = options || {}
95
+ end
96
+
97
+ # Is the bulk write ordered?
98
+ #
99
+ # @api private
100
+ #
101
+ # @example Is the bulk write ordered?
102
+ # bulk_write.ordered?
103
+ #
104
+ # @return [ true, false ] If the bulk write is ordered.
105
+ #
106
+ # @since 2.1.0
107
+ def ordered?
108
+ @ordered ||= options.fetch(:ordered, true)
109
+ end
110
+
111
+ # Get the write concern for the bulk write.
34
112
  #
35
- # @option options [ true, false ] :ordered Whether the operations
36
- # should be executed in order.
37
- # @option options [ Hash ] :write_concern The write concern options.
38
- # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
113
+ # @api private
39
114
  #
40
- # @return [ OrderedBulkWrite, UnorderedBulkWrite ] The appropriate bulk
41
- # write object.
115
+ # @example Get the write concern.
116
+ # bulk_write.write_concern
42
117
  #
43
- # @since 2.0.0
44
- def get(collection, operations, options)
45
- if options.fetch(:ordered, true)
46
- OrderedBulkWrite.new(collection, operations, options)
118
+ # @return [ WriteConcern ] The write concern.
119
+ #
120
+ # @since 2.1.0
121
+ def write_concern
122
+ @write_concern ||= options[:write_concern] ?
123
+ WriteConcern.get(options[:write_concern]) : collection.write_concern
124
+ end
125
+
126
+ private
127
+
128
+ def base_spec(operation_id)
129
+ {
130
+ :db_name => database.name,
131
+ :coll_name => collection.name,
132
+ :write_concern => write_concern,
133
+ :ordered => ordered?,
134
+ :operation_id => operation_id
135
+ }
136
+ end
137
+
138
+ def execute_operation(name, values, server, operation_id, combiner)
139
+ begin
140
+ if values.size > server.max_write_batch_size
141
+ split_execute(name, values, server, operation_id, combiner)
142
+ else
143
+ combiner.combine!(send(name, values, server, operation_id), values.size)
144
+ end
145
+ rescue Error::MaxBSONSize, Error::MaxMessageSize => e
146
+ split_execute(name, values, server, operation_id, combiner)
147
+ end
148
+ end
149
+
150
+ def operations
151
+ if ordered?
152
+ OrderedCombiner.new(requests).combine
47
153
  else
48
- UnorderedBulkWrite.new(collection, operations, options)
154
+ UnorderedCombiner.new(requests).combine
49
155
  end
50
156
  end
157
+
158
+ def split_execute(name, values, server, operation_id, combiner)
159
+ execute_operation(name, values.shift(values.size / 2), server, operation_id, combiner)
160
+ execute_operation(name, values, server, operation_id, combiner)
161
+ end
162
+
163
+ def delete(documents, server, operation_id)
164
+ Operation::Write::Bulk::Delete.new(
165
+ base_spec(operation_id).merge(:deletes => documents)
166
+ ).execute(server.context)
167
+ end
168
+
169
+ alias :delete_one :delete
170
+ alias :delete_many :delete
171
+
172
+ def insert_one(documents, server, operation_id)
173
+ Operation::Write::Bulk::Insert.new(
174
+ base_spec(operation_id).merge(:documents => documents)
175
+ ).execute(server.context)
176
+ end
177
+
178
+ def update(documents, server, operation_id)
179
+ Operation::Write::Bulk::Update.new(
180
+ base_spec(operation_id).merge(:updates => documents)
181
+ ).execute(server.context)
182
+ end
183
+
184
+ alias :replace_one :update
185
+ alias :update_one :update
186
+ alias :update_many :update
51
187
  end
52
188
  end
data/lib/mongo/client.rb CHANGED
@@ -39,6 +39,9 @@ module Mongo
39
39
  # Delegate command execution to the current database.
40
40
  def_delegators :@database, :command
41
41
 
42
+ # Delegate subscription to monitoring.
43
+ def_delegators :@monitoring, :subscribe, :unsubscribe
44
+
42
45
  # Determine if this client is equivalent to another object.
43
46
  #
44
47
  # @example Check client equality.
@@ -119,7 +122,7 @@ module Mongo
119
122
  # attempt a connection.
120
123
  # @option options [ Hash ] :read The read preference options. They consist of a
121
124
  # mode specified as a symbol, an array of hashes known as tag_sets,
122
- # and two timing options: local_threshold and server_selection_timeout.
125
+ # and local_threshold.
123
126
  # :mode can be one of :secondary, :secondary_preferred, :primary,
124
127
  # :primary_preferred, :nearest.
125
128
  # @option options [ Array<Hash, String> ] :roles The list of roles for the
@@ -143,14 +146,21 @@ module Mongo
143
146
  # @option options [ String ] :user The user name.
144
147
  # @option options [ Hash ] :write The write concern options. Can be :w =>
145
148
  # Integer, :fsync => Boolean, :j => Boolean.
149
+ # @option options [ true, false ] :monitoring Initializes a client without
150
+ # any default monitoring if false is provided.
151
+ # @option options [ Logger ] :logger A custom logger if desired.
152
+ # @option options [ true, false ] :truncate_logs Whether to truncate the
153
+ # logs at the default 250 characters.
146
154
  #
147
155
  # @since 2.0.0
148
- def initialize(addresses_or_uri, options = {})
156
+ def initialize(addresses_or_uri, options = Options::Redacted.new)
157
+ @monitoring = Monitoring.new(options)
149
158
  if addresses_or_uri.is_a?(::String)
150
159
  create_from_uri(addresses_or_uri, options)
151
160
  else
152
161
  create_from_addresses(addresses_or_uri, options)
153
162
  end
163
+ yield(self) if block_given?
154
164
  end
155
165
 
156
166
  # Get an inspection of the client as a string.
@@ -175,7 +185,7 @@ module Mongo
175
185
  #
176
186
  # @since 2.0.0
177
187
  def read_preference
178
- @read_preference ||= ServerSelector.get(options[:read] || {}, options)
188
+ @read_preference ||= ServerSelector.get(Options::Redacted.new(options[:read] || {}).merge(options))
179
189
  end
180
190
 
181
191
  # Use the database with the provided name. This will switch the current
@@ -205,13 +215,14 @@ module Mongo
205
215
  # @return [ Mongo::Client ] A new client instance.
206
216
  #
207
217
  # @since 2.0.0
208
- def with(new_options = {})
218
+ def with(new_options = Options::Redacted.new)
209
219
  clone.tap do |client|
210
- client.options.update(new_options)
220
+ opts = Options::Redacted.new(new_options) || Options::Redacted.new
221
+ client.options.update(opts)
211
222
  Database.create(client)
212
223
  # We can't use the same cluster if some options that would affect it
213
224
  # have changed.
214
- if cluster_modifying?(new_options)
225
+ if cluster_modifying?(opts)
215
226
  Cluster.create(client)
216
227
  end
217
228
  end
@@ -230,6 +241,30 @@ module Mongo
230
241
  @write_concern ||= WriteConcern.get(options[:write])
231
242
  end
232
243
 
244
+ # Close all connections.
245
+ #
246
+ # @example Disconnect the client.
247
+ # client.close
248
+ #
249
+ # @return [ true ] Always true.
250
+ #
251
+ # @since 2.1.0
252
+ def close
253
+ @cluster.disconnect! and true
254
+ end
255
+
256
+ # Reconnect the client.
257
+ #
258
+ # @example Reconnect the client.
259
+ # client.reconnect
260
+ #
261
+ # @return [ true ] Always true.
262
+ #
263
+ # @since 2.1.0
264
+ def reconnect
265
+ @cluster.reconnect! and true
266
+ end
267
+
233
268
  # Get the names of all databases.
234
269
  #
235
270
  # @example Get the database names.
@@ -239,7 +274,7 @@ module Mongo
239
274
  #
240
275
  # @since 2.0.5
241
276
  def database_names
242
- list_databases.collect{ |info| info['name'] }
277
+ list_databases.collect{ |info| info[Database::NAME] }
243
278
  end
244
279
 
245
280
  # Get info for each database.
@@ -251,26 +286,27 @@ module Mongo
251
286
  #
252
287
  # @since 2.0.5
253
288
  def list_databases
254
- use(Database::ADMIN).command(listDatabases: 1).first['databases']
289
+ use(Database::ADMIN).command(listDatabases: 1).first[Database::DATABASES]
255
290
  end
256
291
 
257
292
  private
258
293
 
259
- def create_from_addresses(addresses, opts = {})
260
- @options = Database::DEFAULT_OPTIONS.merge(opts).freeze
261
- @cluster = Cluster.new(addresses, options)
294
+ def create_from_addresses(addresses, opts = Options::Redacted.new)
295
+ @options = Options::Redacted.new(Database::DEFAULT_OPTIONS.merge(opts)).freeze
296
+ @cluster = Cluster.new(addresses, @monitoring, options)
262
297
  @database = Database.new(self, options[:database], options)
263
298
  end
264
299
 
265
- def create_from_uri(connection_string, opts = {})
266
- uri = URI.new(connection_string)
267
- @options = Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts)).freeze
268
- @cluster = Cluster.new(uri.servers, options)
300
+ def create_from_uri(connection_string, opts = Options::Redacted.new)
301
+ uri = URI.new(connection_string, opts)
302
+ @options = Options::Redacted.new(Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts))).freeze
303
+ @cluster = Cluster.new(uri.servers, @monitoring, options)
269
304
  @database = Database.new(self, options[:database], options)
270
305
  end
271
306
 
272
307
  def initialize_copy(original)
273
308
  @options = original.options.dup
309
+ @monitoring = Monitoring.new(@options)
274
310
  @database = nil
275
311
  @read_preference = nil
276
312
  @write_concern = nil
@@ -278,7 +314,7 @@ module Mongo
278
314
 
279
315
  def cluster_modifying?(new_options)
280
316
  cluster_options = new_options.reject do |name|
281
- CRUD_OPTIONS.include?(name)
317
+ CRUD_OPTIONS.include?(name.to_sym)
282
318
  end
283
319
  cluster_options.any? do |name, value|
284
320
  options[name] != value
@@ -60,16 +60,20 @@ module Mongo
60
60
  # @return [ ReplicaSet ] The topology.
61
61
  def elect_primary(description, servers)
62
62
  if description.replica_set_name == replica_set_name
63
- log_debug([ "Server #{description.address.to_s} elected as primary in #{replica_set_name}." ])
64
- servers.each do |server|
65
- if server.primary? && server.address != description.address
66
- server.description.unknown!
63
+ unless detect_stale_primary!(description)
64
+ log_debug("Server #{description.address.to_s} elected as primary in #{replica_set_name}.")
65
+ servers.each do |server|
66
+ if server.primary? && server.address != description.address
67
+ server.description.unknown!
68
+ end
67
69
  end
70
+ update_max_election_id(description)
68
71
  end
69
72
  else
70
- log_warn([
71
- "Server #{description.address.to_s} in incorrect replica set: #{description.replica_set_name}."
72
- ])
73
+ log_warn(
74
+ "Server #{description.address.to_s} has incorrect replica set name: " +
75
+ "'#{description.replica_set_name}'. The current replica set name is '#{replica_set_name}'."
76
+ )
73
77
  end
74
78
  self
75
79
  end
@@ -84,6 +88,7 @@ module Mongo
84
88
  # @since 2.0.0
85
89
  def initialize(options, seeds = [])
86
90
  @options = options
91
+ @max_election_id = 0
87
92
  end
88
93
 
89
94
  # A replica set topology is a replica set.
@@ -153,8 +158,9 @@ module Mongo
153
158
  def remove_hosts?(description)
154
159
  !description.config.empty? &&
155
160
  (description.primary? ||
156
- description.hosts.empty? ||
157
- !member_of_this_set?(description))
161
+ description.me_mismatch? ||
162
+ description.hosts.empty? ||
163
+ !member_of_this_set?(description))
158
164
  end
159
165
 
160
166
  # Whether a specific server in the cluster can be removed, given a description.
@@ -215,6 +221,18 @@ module Mongo
215
221
 
216
222
  private
217
223
 
224
+ def update_max_election_id(description)
225
+ if description.election_id && description.election_id > @max_election_id
226
+ @max_election_id = description.election_id
227
+ end
228
+ end
229
+
230
+ def detect_stale_primary!(description)
231
+ if description.election_id && description.election_id < @max_election_id
232
+ description.unknown!
233
+ end
234
+ end
235
+
218
236
  def has_primary?(servers)
219
237
  servers.find { |s| s.primary? }
220
238
  end
@@ -184,7 +184,7 @@ module Mongo
184
184
  private
185
185
 
186
186
  def remove_self?(description, server)
187
- description.is_server?(server) && !description.mongos?
187
+ description.is_server?(server) && !(description.mongos? || description.unknown?)
188
188
  end
189
189
  end
190
190
  end
@@ -55,7 +55,7 @@ module Mongo
55
55
  # @return [ Sharded, ReplicaSet ] The new topology.
56
56
  def elect_primary(description, servers)
57
57
  if description.mongos?
58
- log_debug([ "Mongos #{description.address.to_s} discovered." ])
58
+ log_debug("Mongos #{description.address.to_s} discovered.")
59
59
  Sharded.new(options)
60
60
  else
61
61
  initialize_replica_set(description, servers)
@@ -204,7 +204,10 @@ module Mongo
204
204
  private
205
205
 
206
206
  def initialize_replica_set(description, servers)
207
- log_debug([ "Server #{description.address.to_s} discovered as primary." ])
207
+ log_debug(
208
+ "Server #{description.address.to_s} discovered as primary in replica set: " +
209
+ "'#{description.replica_set_name}'. Changing topology to replica set."
210
+ )
208
211
  servers.each do |server|
209
212
  if server.standalone? && server.address != description.address
210
213
  server.description.unknown!