mongo 2.13.0.beta1 → 2.14.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 (339) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +50 -9
  5. data/lib/mongo.rb +13 -2
  6. data/lib/mongo/address.rb +1 -1
  7. data/lib/mongo/address/ipv4.rb +1 -1
  8. data/lib/mongo/address/ipv6.rb +1 -1
  9. data/lib/mongo/auth/aws/request.rb +31 -5
  10. data/lib/mongo/bulk_write.rb +18 -0
  11. data/lib/mongo/caching_cursor.rb +74 -0
  12. data/lib/mongo/client.rb +238 -31
  13. data/lib/mongo/cluster.rb +56 -20
  14. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  15. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  16. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  17. data/lib/mongo/cluster/topology/single.rb +2 -2
  18. data/lib/mongo/collection.rb +66 -24
  19. data/lib/mongo/collection/view.rb +24 -20
  20. data/lib/mongo/collection/view/aggregation.rb +25 -4
  21. data/lib/mongo/collection/view/builder/find_command.rb +38 -18
  22. data/lib/mongo/collection/view/explainable.rb +27 -8
  23. data/lib/mongo/collection/view/iterable.rb +72 -12
  24. data/lib/mongo/collection/view/readable.rb +19 -3
  25. data/lib/mongo/collection/view/writable.rb +55 -5
  26. data/lib/mongo/crypt/encryption_io.rb +6 -6
  27. data/lib/mongo/cursor.rb +16 -3
  28. data/lib/mongo/database.rb +37 -4
  29. data/lib/mongo/database/view.rb +18 -3
  30. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  31. data/lib/mongo/error.rb +5 -0
  32. data/lib/mongo/error/invalid_read_concern.rb +28 -0
  33. data/lib/mongo/error/invalid_server_auth_host.rb +22 -0
  34. data/lib/mongo/error/invalid_session.rb +2 -1
  35. data/lib/mongo/error/operation_failure.rb +11 -5
  36. data/lib/mongo/error/server_certificate_revoked.rb +22 -0
  37. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  38. data/lib/mongo/error/unsupported_option.rb +14 -12
  39. data/lib/mongo/event/base.rb +6 -0
  40. data/lib/mongo/grid/file.rb +5 -0
  41. data/lib/mongo/grid/file/chunk.rb +2 -0
  42. data/lib/mongo/grid/fs_bucket.rb +15 -13
  43. data/lib/mongo/grid/stream/write.rb +9 -3
  44. data/lib/mongo/index/view.rb +3 -0
  45. data/lib/mongo/lint.rb +2 -1
  46. data/lib/mongo/logger.rb +3 -3
  47. data/lib/mongo/monitoring.rb +38 -0
  48. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  49. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  50. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  51. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  52. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  53. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  54. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  55. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  56. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  57. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  58. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  59. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  60. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  61. data/lib/mongo/monitoring/publishable.rb +6 -3
  62. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  63. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  64. data/lib/mongo/operation.rb +2 -0
  65. data/lib/mongo/operation/aggregate/result.rb +9 -8
  66. data/lib/mongo/operation/collections_info/command.rb +5 -0
  67. data/lib/mongo/operation/collections_info/result.rb +18 -1
  68. data/lib/mongo/operation/delete/bulk_result.rb +2 -0
  69. data/lib/mongo/operation/delete/result.rb +3 -0
  70. data/lib/mongo/operation/explain/command.rb +4 -0
  71. data/lib/mongo/operation/explain/legacy.rb +4 -0
  72. data/lib/mongo/operation/explain/op_msg.rb +6 -0
  73. data/lib/mongo/operation/explain/result.rb +3 -0
  74. data/lib/mongo/operation/find/legacy/result.rb +2 -0
  75. data/lib/mongo/operation/find/result.rb +13 -0
  76. data/lib/mongo/operation/get_more/result.rb +3 -0
  77. data/lib/mongo/operation/indexes/result.rb +5 -0
  78. data/lib/mongo/operation/insert/bulk_result.rb +5 -0
  79. data/lib/mongo/operation/insert/result.rb +5 -0
  80. data/lib/mongo/operation/list_collections/result.rb +5 -0
  81. data/lib/mongo/operation/map_reduce/result.rb +10 -0
  82. data/lib/mongo/operation/parallel_scan/result.rb +4 -0
  83. data/lib/mongo/operation/result.rb +35 -6
  84. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
  85. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
  86. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
  87. data/lib/mongo/operation/shared/executable.rb +1 -0
  88. data/lib/mongo/operation/shared/idable.rb +2 -1
  89. data/lib/mongo/operation/shared/limited.rb +1 -0
  90. data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
  91. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
  92. data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
  93. data/lib/mongo/operation/shared/specifiable.rb +1 -0
  94. data/lib/mongo/operation/shared/write.rb +1 -0
  95. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
  96. data/lib/mongo/operation/update/legacy/result.rb +7 -0
  97. data/lib/mongo/operation/update/result.rb +8 -0
  98. data/lib/mongo/operation/users_info/result.rb +3 -0
  99. data/lib/mongo/protocol/message.rb +47 -10
  100. data/lib/mongo/protocol/msg.rb +34 -1
  101. data/lib/mongo/protocol/query.rb +36 -0
  102. data/lib/mongo/protocol/serializers.rb +5 -2
  103. data/lib/mongo/query_cache.rb +242 -0
  104. data/lib/mongo/retryable.rb +8 -1
  105. data/lib/mongo/server.rb +15 -4
  106. data/lib/mongo/server/app_metadata.rb +27 -3
  107. data/lib/mongo/server/connection.rb +4 -4
  108. data/lib/mongo/server/connection_base.rb +38 -12
  109. data/lib/mongo/server/connection_common.rb +2 -2
  110. data/lib/mongo/server/connection_pool.rb +3 -0
  111. data/lib/mongo/server/description.rb +13 -1
  112. data/lib/mongo/server/monitor.rb +76 -44
  113. data/lib/mongo/server/monitor/connection.rb +57 -9
  114. data/lib/mongo/server/pending_connection.rb +14 -4
  115. data/lib/mongo/server/push_monitor.rb +173 -0
  116. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  117. data/lib/mongo/server_selector.rb +0 -1
  118. data/lib/mongo/server_selector/base.rb +583 -1
  119. data/lib/mongo/server_selector/nearest.rb +1 -6
  120. data/lib/mongo/server_selector/primary.rb +1 -6
  121. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  122. data/lib/mongo/server_selector/secondary.rb +1 -6
  123. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  124. data/lib/mongo/session.rb +7 -1
  125. data/lib/mongo/socket.rb +26 -12
  126. data/lib/mongo/socket/ocsp_cache.rb +97 -0
  127. data/lib/mongo/socket/ocsp_verifier.rb +368 -0
  128. data/lib/mongo/socket/ssl.rb +46 -25
  129. data/lib/mongo/socket/tcp.rb +1 -1
  130. data/lib/mongo/srv/monitor.rb +7 -13
  131. data/lib/mongo/srv/resolver.rb +14 -10
  132. data/lib/mongo/timeout.rb +2 -0
  133. data/lib/mongo/topology_version.rb +9 -0
  134. data/lib/mongo/uri.rb +21 -390
  135. data/lib/mongo/uri/options_mapper.rb +582 -0
  136. data/lib/mongo/uri/srv_protocol.rb +3 -2
  137. data/lib/mongo/utils.rb +73 -0
  138. data/lib/mongo/version.rb +1 -1
  139. data/spec/NOTES.aws-auth.md +12 -7
  140. data/spec/README.aws-auth.md +2 -2
  141. data/spec/README.md +63 -1
  142. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  143. data/spec/integration/bson_symbol_spec.rb +4 -2
  144. data/spec/integration/bulk_write_spec.rb +67 -0
  145. data/spec/integration/change_stream_examples_spec.rb +6 -2
  146. data/spec/integration/change_stream_spec.rb +1 -1
  147. data/spec/integration/check_clean_slate_spec.rb +16 -0
  148. data/spec/integration/client_authentication_options_spec.rb +92 -28
  149. data/spec/integration/client_construction_spec.rb +1 -0
  150. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +9 -5
  151. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  152. data/spec/integration/connection_pool_populator_spec.rb +4 -2
  153. data/spec/integration/connection_spec.rb +7 -4
  154. data/spec/integration/crud_spec.rb +4 -4
  155. data/spec/integration/cursor_reaping_spec.rb +54 -18
  156. data/spec/integration/docs_examples_spec.rb +6 -0
  157. data/spec/integration/fork_reconnect_spec.rb +56 -1
  158. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  159. data/spec/integration/heartbeat_events_spec.rb +4 -23
  160. data/spec/integration/ocsp_connectivity_spec.rb +26 -0
  161. data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
  162. data/spec/integration/ocsp_verifier_spec.rb +334 -0
  163. data/spec/integration/query_cache_spec.rb +1045 -0
  164. data/spec/integration/query_cache_transactions_spec.rb +190 -0
  165. data/spec/integration/read_concern_spec.rb +1 -1
  166. data/spec/integration/retryable_errors_spec.rb +1 -1
  167. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
  168. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +4 -2
  169. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  170. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  171. data/spec/integration/sdam_error_handling_spec.rb +122 -15
  172. data/spec/integration/sdam_events_spec.rb +80 -6
  173. data/spec/integration/sdam_prose_spec.rb +64 -0
  174. data/spec/integration/server_monitor_spec.rb +25 -1
  175. data/spec/integration/server_selection_spec.rb +36 -0
  176. data/spec/integration/size_limit_spec.rb +23 -5
  177. data/spec/integration/srv_monitoring_spec.rb +38 -3
  178. data/spec/integration/srv_spec.rb +56 -0
  179. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  180. data/spec/integration/transactions_examples_spec.rb +17 -7
  181. data/spec/integration/zlib_compression_spec.rb +25 -0
  182. data/spec/lite_spec_helper.rb +20 -9
  183. data/spec/mongo/address_spec.rb +1 -1
  184. data/spec/mongo/auth/aws/request_region_spec.rb +42 -0
  185. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  186. data/spec/mongo/auth/scram_spec.rb +1 -1
  187. data/spec/mongo/auth/user_spec.rb +1 -1
  188. data/spec/mongo/bulk_write_spec.rb +2 -2
  189. data/spec/mongo/caching_cursor_spec.rb +70 -0
  190. data/spec/mongo/client_construction_spec.rb +386 -3
  191. data/spec/mongo/client_encryption_spec.rb +16 -10
  192. data/spec/mongo/client_spec.rb +85 -3
  193. data/spec/mongo/cluster/topology/replica_set_spec.rb +53 -10
  194. data/spec/mongo/cluster/topology/sharded_spec.rb +1 -1
  195. data/spec/mongo/cluster/topology/single_spec.rb +19 -8
  196. data/spec/mongo/cluster/topology/unknown_spec.rb +1 -1
  197. data/spec/mongo/cluster/topology_spec.rb +1 -1
  198. data/spec/mongo/cluster_spec.rb +37 -35
  199. data/spec/mongo/collection/view/change_stream_resume_spec.rb +7 -7
  200. data/spec/mongo/collection/view/explainable_spec.rb +87 -4
  201. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
  202. data/spec/mongo/collection/view/readable_spec.rb +36 -0
  203. data/spec/mongo/collection_spec.rb +572 -0
  204. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  205. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  206. data/spec/mongo/crypt/binary_spec.rb +1 -6
  207. data/spec/mongo/crypt/binding/binary_spec.rb +1 -6
  208. data/spec/mongo/crypt/binding/context_spec.rb +2 -7
  209. data/spec/mongo/crypt/binding/helpers_spec.rb +1 -6
  210. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +2 -7
  211. data/spec/mongo/crypt/binding/status_spec.rb +1 -6
  212. data/spec/mongo/crypt/binding/version_spec.rb +1 -6
  213. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  214. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  215. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
  216. data/spec/mongo/crypt/status_spec.rb +1 -6
  217. data/spec/mongo/database_spec.rb +353 -8
  218. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  219. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  220. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  221. data/spec/mongo/index/view_spec.rb +148 -2
  222. data/spec/mongo/logger_spec.rb +13 -11
  223. data/spec/mongo/monitoring/event/server_closed_spec.rb +1 -1
  224. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  225. data/spec/mongo/monitoring/event/server_opening_spec.rb +1 -1
  226. data/spec/mongo/monitoring/event/topology_changed_spec.rb +1 -1
  227. data/spec/mongo/monitoring/event/topology_closed_spec.rb +1 -1
  228. data/spec/mongo/monitoring/event/topology_opening_spec.rb +1 -1
  229. data/spec/mongo/operation/delete/op_msg_spec.rb +3 -3
  230. data/spec/mongo/operation/insert/command_spec.rb +2 -2
  231. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -3
  232. data/spec/mongo/operation/read_preference_op_msg_spec.rb +1 -1
  233. data/spec/mongo/operation/update/command_spec.rb +2 -2
  234. data/spec/mongo/operation/update/op_msg_spec.rb +3 -3
  235. data/spec/mongo/protocol/msg_spec.rb +10 -0
  236. data/spec/mongo/query_cache_spec.rb +280 -0
  237. data/spec/mongo/semaphore_spec.rb +51 -0
  238. data/spec/mongo/server/app_metadata_shared.rb +82 -2
  239. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  240. data/spec/mongo/server/connection_pool_spec.rb +7 -3
  241. data/spec/mongo/server/connection_spec.rb +15 -8
  242. data/spec/mongo/server/description_spec.rb +18 -0
  243. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  244. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  245. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  246. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  247. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  248. data/spec/mongo/server_selector_spec.rb +6 -6
  249. data/spec/mongo/session_spec.rb +35 -0
  250. data/spec/mongo/socket/ssl_spec.rb +4 -4
  251. data/spec/mongo/socket_spec.rb +1 -1
  252. data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
  253. data/spec/mongo/uri_option_parsing_spec.rb +11 -11
  254. data/spec/mongo/uri_spec.rb +68 -41
  255. data/spec/mongo/utils_spec.rb +39 -0
  256. data/spec/runners/auth.rb +3 -0
  257. data/spec/runners/change_streams/test.rb +3 -3
  258. data/spec/runners/cmap.rb +1 -1
  259. data/spec/runners/command_monitoring.rb +3 -34
  260. data/spec/runners/connection_string.rb +35 -124
  261. data/spec/runners/crud/context.rb +9 -5
  262. data/spec/runners/crud/operation.rb +59 -27
  263. data/spec/runners/crud/spec.rb +0 -8
  264. data/spec/runners/crud/test.rb +1 -1
  265. data/spec/runners/crud/test_base.rb +0 -19
  266. data/spec/runners/sdam.rb +2 -2
  267. data/spec/runners/server_selection.rb +242 -28
  268. data/spec/runners/transactions.rb +12 -12
  269. data/spec/runners/transactions/operation.rb +151 -25
  270. data/spec/runners/transactions/test.rb +62 -18
  271. data/spec/shared/LICENSE +20 -0
  272. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  273. data/spec/shared/lib/mrss/constraints.rb +303 -0
  274. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  275. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  276. data/spec/spec_helper.rb +3 -1
  277. data/spec/spec_tests/cmap_spec.rb +7 -3
  278. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  279. data/spec/spec_tests/crud_spec.rb +1 -1
  280. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -9
  281. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  282. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  283. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  284. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  285. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  288. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  289. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  290. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  291. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  292. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  293. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  294. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  295. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  296. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  297. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  298. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  299. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
  300. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
  301. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  302. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  303. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  304. data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
  305. data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
  306. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  307. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
  308. data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
  309. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
  310. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  311. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  312. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  313. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  314. data/spec/spec_tests/server_selection_spec.rb +4 -116
  315. data/spec/spec_tests/uri_options_spec.rb +31 -33
  316. data/spec/stress/cleanup_spec.rb +17 -2
  317. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  318. data/spec/stress/fork_reconnect_stress_spec.rb +1 -1
  319. data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
  320. data/spec/support/certificates/atlas-ocsp.crt +41 -0
  321. data/spec/support/client_registry.rb +1 -0
  322. data/spec/support/client_registry_macros.rb +11 -2
  323. data/spec/support/cluster_config.rb +4 -0
  324. data/spec/support/common_shortcuts.rb +45 -0
  325. data/spec/support/constraints.rb +6 -253
  326. data/spec/support/event_subscriber.rb +123 -33
  327. data/spec/support/keyword_struct.rb +26 -0
  328. data/spec/support/matchers.rb +16 -0
  329. data/spec/support/ocsp +1 -0
  330. data/spec/support/session_registry.rb +52 -0
  331. data/spec/support/shared/server_selector.rb +13 -1
  332. data/spec/support/spec_config.rb +60 -13
  333. data/spec/support/spec_setup.rb +1 -1
  334. data/spec/support/utils.rb +84 -1
  335. metadata +1027 -937
  336. metadata.gz.sig +0 -0
  337. data/lib/mongo/server_selector/selectable.rb +0 -560
  338. data/spec/runners/sdam_monitoring.rb +0 -89
  339. data/spec/support/lite_constraints.rb +0 -141
@@ -89,6 +89,16 @@ module Mongo
89
89
  self.class.new(view, pipeline, options.merge(explain: true)).first
90
90
  end
91
91
 
92
+ # Whether this aggregation will write its result to a database collection.
93
+ #
94
+ # @return [ Boolean ] Whether the aggregation will write its result
95
+ # to a collection.
96
+ #
97
+ # @api private
98
+ def write?
99
+ pipeline.any? { |op| op.key?('$out') || op.key?(:$out) || op.key?('$merge') || op.key?(:$merge) }
100
+ end
101
+
92
102
  private
93
103
 
94
104
  def server_selector
@@ -114,10 +124,6 @@ module Mongo
114
124
  description.standalone? || description.mongos? || description.primary? || secondary_ok?
115
125
  end
116
126
 
117
- def write?
118
- pipeline.any? { |op| op.key?('$out') || op.key?(:$out) || op.key?('$merge') || op.key?(:$merge) }
119
- end
120
-
121
127
  def secondary_ok?
122
128
  !write?
123
129
  end
@@ -136,6 +142,21 @@ module Mongo
136
142
  raise Error::UnsupportedCollation.new
137
143
  end
138
144
  end
145
+
146
+ # Skip, sort, limit, projection are specified as pipeline stages
147
+ # rather than as options.
148
+ def cache_options
149
+ {
150
+ namespace: collection.namespace,
151
+ selector: pipeline,
152
+ read_concern: view.read_concern,
153
+ read_preference: view.read_preference,
154
+ collation: options[:collation],
155
+ # Aggregations can read documents from more than one collection,
156
+ # so they will be cleared on every write operation.
157
+ multi_collection: true,
158
+ }
159
+ end
139
160
  end
140
161
  end
141
162
  end
@@ -52,21 +52,6 @@ module Mongo
52
52
  collation: 'collation'
53
53
  ).freeze
54
54
 
55
- def_delegators :@view, :collection, :database, :filter, :options, :read
56
-
57
- # Get the specification for an explain command that wraps the find
58
- # command.
59
- #
60
- # @example Get the explain spec.
61
- # builder.explain_specification
62
- #
63
- # @return [ Hash ] The specification.
64
- #
65
- # @since 2.2.0
66
- def explain_specification
67
- { selector: { explain: find_command }, db_name: database.name, read: read, session: @session }
68
- end
69
-
70
55
  # Create the find command builder.
71
56
  #
72
57
  # @example Create the find command builder.
@@ -81,6 +66,8 @@ module Mongo
81
66
  @session = session
82
67
  end
83
68
 
69
+ def_delegators :@view, :collection, :database, :filter, :options, :read
70
+
84
71
  # Get the specification to pass to the find command operation.
85
72
  #
86
73
  # @example Get the specification.
@@ -90,18 +77,51 @@ module Mongo
90
77
  #
91
78
  # @since 2.2.0
92
79
  def specification
93
- { selector: find_command, db_name: database.name, read: read, session: @session }
80
+ {
81
+ selector: find_command,
82
+ db_name: database.name,
83
+ read: read,
84
+ session: @session,
85
+ }
86
+ end
87
+
88
+ # Get the specification for an explain command that wraps the find
89
+ # command.
90
+ #
91
+ # @example Get the explain spec.
92
+ # builder.explain_specification
93
+ #
94
+ # @return [ Hash ] The specification.
95
+ #
96
+ # @since 2.2.0
97
+ def explain_specification
98
+ {
99
+ selector: {
100
+ explain: find_command,
101
+ },
102
+ db_name: database.name,
103
+ read: read,
104
+ session: @session,
105
+ # We should always have options{:explain] set if we are explaining.
106
+ # The explain field is not sent to the server, it will be
107
+ # processed in the operation layer.
108
+ explain: options[:explain],
109
+ }
94
110
  end
95
111
 
96
112
  private
97
113
 
98
114
  def find_command
99
- document = BSON::Document.new('find' => collection.name, 'filter' => filter)
115
+ document = BSON::Document.new(
116
+ find: collection.name,
117
+ filter: filter,
118
+ )
100
119
  if collection.read_concern
101
120
  document[:readConcern] = Options::Mapper.transform_values_to_strings(
102
121
  collection.read_concern)
103
122
  end
104
- command = Options::Mapper.transform_documents(convert_flags(options), MAPPINGS, document)
123
+ command = Options::Mapper.transform_documents(
124
+ convert_flags(options), MAPPINGS, document)
105
125
  if command['oplogReplay']
106
126
  log_warn("oplogReplay is deprecated and ignored by MongoDB 4.4 and later")
107
127
  end
@@ -36,16 +36,25 @@ module Mongo
36
36
  # @since 2.2.0
37
37
  ALL_PLANS_EXECUTION = 'allPlansExecution'.freeze
38
38
 
39
- # Get the explain plan for the query.
39
+ # Get the query plan for the query.
40
40
  #
41
- # @example Get the explain plan for the query.
42
- # view.explain
41
+ # @example Get the query plan for the query with execution statistics.
42
+ # view.explain(verbosity: :execution_stats)
43
43
  #
44
- # @return [ Hash ] A single document with the explain plan.
44
+ # @option opts [ true | false ] :verbose The level of detail
45
+ # to return for MongoDB 2.6 servers.
46
+ # @option opts [ String | Symbol ] :verbosity The type of information
47
+ # to return for MongoDB 3.0 and newer servers. If the value is a
48
+ # symbol, it will be stringified and converted from underscore
49
+ # style to camel case style (e.g. :query_planner => "queryPlanner").
50
+ #
51
+ # @return [ Hash ] A single document with the query plan.
52
+ #
53
+ # @see https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain
45
54
  #
46
55
  # @since 2.0.0
47
- def explain
48
- self.class.new(collection, selector, options.merge(explain_options)).first
56
+ def explain(**opts)
57
+ self.class.new(collection, selector, options.merge(explain_options(**opts))).first
49
58
  end
50
59
 
51
60
  private
@@ -54,9 +63,19 @@ module Mongo
54
63
  !!options[:explain]
55
64
  end
56
65
 
57
- def explain_options
66
+ # @option opts [ true | false ] :verbose The level of detail
67
+ # to return for MongoDB 2.6 servers.
68
+ # @option opts [ String | Symbol ] :verbosity The type of information
69
+ # to return for MongoDB 3.0 and newer servers. If the value is a
70
+ # symbol, it will be stringified and converted from underscore
71
+ # style to camel case style (e.g. :query_planner => "queryPlanner").
72
+ def explain_options(**opts)
58
73
  explain_limit = limit || 0
59
- { :limit => -explain_limit.abs, :explain => true }
74
+ # Note: opts will never be nil here.
75
+ if Symbol === opts[:verbosity]
76
+ opts[:verbosity] = Utils.camelize(opts[:verbosity])
77
+ end
78
+ { limit: -explain_limit.abs, explain: opts }
60
79
  end
61
80
  end
62
81
  end
@@ -35,19 +35,34 @@ module Mongo
35
35
  #
36
36
  # @yieldparam [ Hash ] Each matching document.
37
37
  def each
38
- @cursor = nil
39
- session = client.send(:get_session, @options)
40
- @cursor = if respond_to?(:write?, true) && write?
41
- server = server_selector.select_server(cluster, nil, session)
42
- result = send_initial_query(server, session)
43
- Cursor.new(view, result, server, session: session)
38
+ @cursor = if use_query_cache? && cached_cursor
39
+ cached_cursor
44
40
  else
45
- read_with_retry_cursor(session, server_selector, view) do |server|
46
- send_initial_query(server, session)
47
- end
41
+ session = client.send(:get_session, @options)
42
+ select_cursor(session)
43
+ end
44
+
45
+ if use_query_cache?
46
+ # No need to store the cursor in the query cache if there is
47
+ # already a cached cursor stored at this key.
48
+ QueryCache.set(@cursor, **cache_options) unless cached_cursor
49
+
50
+ # If a query with a limit is performed, the query cache will
51
+ # re-use results from an earlier query with the same or larger
52
+ # limit, and then impose the lower limit during iteration.
53
+ limit_for_cached_query = respond_to?(:limit) ? limit : nil
48
54
  end
55
+
49
56
  if block_given?
50
- @cursor.each do |doc|
57
+ # Ruby versions 2.5 and older do not support arr[0..nil] syntax, so
58
+ # this must be a separate conditional.
59
+ cursor_to_iterate = if limit_for_cached_query
60
+ @cursor.to_a[0...limit_for_cached_query]
61
+ else
62
+ @cursor
63
+ end
64
+
65
+ cursor_to_iterate.each do |doc|
51
66
  yield doc
52
67
  end
53
68
  else
@@ -77,6 +92,46 @@ module Mongo
77
92
 
78
93
  private
79
94
 
95
+ def select_cursor(session)
96
+ if respond_to?(:write?, true) && write?
97
+ server = server_selector.select_server(cluster, nil, session)
98
+ result = send_initial_query(server, session)
99
+
100
+ # RUBY-2367: This will be updated to allow the query cache to
101
+ # cache cursors with multi-batch results.
102
+ if use_query_cache?
103
+ CachingCursor.new(view, result, server, session: session)
104
+ else
105
+ Cursor.new(view, result, server, session: session)
106
+ end
107
+ else
108
+ read_with_retry_cursor(session, server_selector, view) do |server|
109
+ send_initial_query(server, session)
110
+ end
111
+ end
112
+ end
113
+
114
+ def cached_cursor
115
+ QueryCache.get(**cache_options)
116
+ end
117
+
118
+ def cache_options
119
+ # NB: this hash is passed as keyword argument and must have symbol
120
+ # keys.
121
+ {
122
+ namespace: collection.namespace,
123
+ selector: selector,
124
+ skip: skip,
125
+ sort: sort,
126
+ limit: limit,
127
+ projection: projection,
128
+ collation: collation,
129
+ read_concern: read_concern,
130
+ read_preference: read_preference
131
+
132
+ }
133
+ end
134
+
80
135
  def initial_query_op(server, session)
81
136
  if server.with_connection { |connection| connection.features }.find_command_enabled?
82
137
  initial_command_op(session)
@@ -92,10 +147,11 @@ module Mongo
92
147
  end
93
148
 
94
149
  def initial_command_op(session)
150
+ builder = Builder::FindCommand.new(self, session)
95
151
  if explained?
96
- Operation::Explain.new(Builder::FindCommand.new(self, session).explain_specification)
152
+ Operation::Explain.new(builder.explain_specification)
97
153
  else
98
- Operation::Find.new(Builder::FindCommand.new(self, session).specification)
154
+ Operation::Find.new(builder.specification)
99
155
  end
100
156
  end
101
157
 
@@ -103,6 +159,10 @@ module Mongo
103
159
  validate_collation!(server, collation)
104
160
  initial_query_op(server, session).execute(server, client: client)
105
161
  end
162
+
163
+ def use_query_cache?
164
+ QueryCache.enabled? && !collection.system_collection?
165
+ end
106
166
  end
107
167
  end
108
168
  end
@@ -45,7 +45,17 @@ module Mongo
45
45
  #
46
46
  # @since 2.0.0
47
47
  def aggregate(pipeline, options = {})
48
- Aggregation.new(self, pipeline, options)
48
+ aggregation = Aggregation.new(self, pipeline, options)
49
+
50
+ # Because the $merge and $out pipeline stages write documents to the
51
+ # collection, it is necessary to clear the cache when they are performed.
52
+ #
53
+ # Opt to clear the entire cache rather than one namespace because
54
+ # the $out and $merge stages do not have to write to the same namespace
55
+ # on which the aggregation is performed.
56
+ QueryCache.clear if aggregation.write?
57
+
58
+ aggregation
49
59
  end
50
60
 
51
61
  # Allows the server to write temporary data to disk while executing
@@ -90,7 +100,7 @@ module Mongo
90
100
  # @param [ Integer ] batch_size The size of each batch of results.
91
101
  #
92
102
  # @return [ Integer, View ] Either the batch_size value or a
93
- # new +View+.
103
+ # new +View+.
94
104
  #
95
105
  # @since 2.0.0
96
106
  def batch_size(batch_size = nil)
@@ -193,7 +203,9 @@ module Mongo
193
203
  pipeline << { :'$limit' => opts[:limit] } if opts[:limit]
194
204
  pipeline << { :'$group' => { _id: 1, n: { :'$sum' => 1 } } }
195
205
 
196
- opts.select! { |k, _| [:hint, :max_time_ms, :read, :collation, :session].include?(k) }
206
+ opts = opts.select { |k, _| [:hint, :max_time_ms, :read, :collation, :session].include?(k) }
207
+ opts[:collation] ||= collation
208
+
197
209
  first = aggregate(pipeline, opts).first
198
210
  return 0 unless first
199
211
  first['n'].to_i
@@ -214,6 +226,10 @@ module Mongo
214
226
  #
215
227
  # @since 2.6.0
216
228
  def estimated_document_count(opts = {})
229
+ unless view.filter.empty?
230
+ raise ArgumentError, "Cannot call estimated_document_count when querying with a filter"
231
+ end
232
+
217
233
  cmd = { count: collection.name }
218
234
  cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
219
235
  if read_concern
@@ -48,10 +48,15 @@ module Mongo
48
48
  #
49
49
  # @since 2.0.0
50
50
  def find_one_and_delete(opts = {})
51
+ QueryCache.clear_namespace(collection.namespace)
52
+
51
53
  cmd = { :findAndModify => collection.name, :query => filter, :remove => true }
52
54
  cmd[:fields] = projection if projection
53
55
  cmd[:sort] = sort if sort
54
56
  cmd[:maxTimeMS] = max_time_ms if max_time_ms
57
+ if opts[:bypass_document_validation]
58
+ cmd[:bypassDocumentValidation] = true
59
+ end
55
60
 
56
61
  with_session(opts) do |session|
57
62
  applied_write_concern = applied_write_concern(session)
@@ -124,6 +129,8 @@ module Mongo
124
129
  #
125
130
  # @since 2.0.0
126
131
  def find_one_and_update(document, opts = {})
132
+ QueryCache.clear_namespace(collection.namespace)
133
+
127
134
  cmd = { :findAndModify => collection.name, :query => filter }
128
135
  cmd[:update] = document
129
136
  cmd[:fields] = projection if projection
@@ -165,14 +172,22 @@ module Mongo
165
172
  # @option opts [ Session ] :session The session to use.
166
173
  # @option opts [ Hash | String ] :hint The index to use for this operation.
167
174
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
175
+ # @option opts [ Hash ] :write_concern The write concern options.
176
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
168
177
  #
169
178
  # @return [ Result ] The response from the database.
170
179
  #
171
180
  # @since 2.0.0
172
181
  def delete_many(opts = {})
182
+ QueryCache.clear_namespace(collection.namespace)
183
+
173
184
  delete_doc = { Operation::Q => filter, Operation::LIMIT => 0 }
174
185
  with_session(opts) do |session|
175
- write_concern = write_concern_with_session(session)
186
+ write_concern = if opts[:write_concern]
187
+ WriteConcern.get(opts[:write_concern])
188
+ else
189
+ write_concern_with_session(session)
190
+ end
176
191
  nro_write_with_retry(session, write_concern) do |server|
177
192
  apply_collation!(delete_doc, server, opts)
178
193
  apply_hint!(delete_doc, server, opts.merge(write_concern: write_concern))
@@ -182,6 +197,7 @@ module Mongo
182
197
  :db_name => collection.database.name,
183
198
  :coll_name => collection.name,
184
199
  :write_concern => write_concern,
200
+ :bypass_document_validation => !!opts[:bypass_document_validation],
185
201
  :session => session
186
202
  ).execute(server, client: client)
187
203
  end
@@ -199,14 +215,22 @@ module Mongo
199
215
  # @option opts [ Session ] :session The session to use.
200
216
  # @option opts [ Hash | String ] :hint The index to use for this operation.
201
217
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
218
+ # @option opts [ Hash ] :write_concern The write concern options.
219
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
202
220
  #
203
221
  # @return [ Result ] The response from the database.
204
222
  #
205
223
  # @since 2.0.0
206
224
  def delete_one(opts = {})
225
+ QueryCache.clear_namespace(collection.namespace)
226
+
207
227
  delete_doc = { Operation::Q => filter, Operation::LIMIT => 1 }
208
228
  with_session(opts) do |session|
209
- write_concern = write_concern_with_session(session)
229
+ write_concern = if opts[:write_concern]
230
+ WriteConcern.get(opts[:write_concern])
231
+ else
232
+ write_concern_with_session(session)
233
+ end
210
234
  write_with_retry(session, write_concern) do |server, txn_num|
211
235
  apply_collation!(delete_doc, server, opts)
212
236
  apply_hint!(delete_doc, server, opts.merge(write_concern: write_concern))
@@ -216,6 +240,7 @@ module Mongo
216
240
  :db_name => collection.database.name,
217
241
  :coll_name => collection.name,
218
242
  :write_concern => write_concern,
243
+ :bypass_document_validation => !!opts[:bypass_document_validation],
219
244
  :session => session,
220
245
  :txn_num => txn_num
221
246
  ).execute(server, client: client)
@@ -239,11 +264,15 @@ module Mongo
239
264
  # @option opts [ Session ] :session The session to use.
240
265
  # @option opts [ Hash | String ] :hint The index to use for this operation.
241
266
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
267
+ # @option opts [ Hash ] :write_concern The write concern options.
268
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
242
269
  #
243
270
  # @return [ Result ] The response from the database.
244
271
  #
245
272
  # @since 2.0.0
246
273
  def replace_one(replacement, opts = {})
274
+ QueryCache.clear_namespace(collection.namespace)
275
+
247
276
  update_doc = { Operation::Q => filter,
248
277
  Operation::U => replacement,
249
278
  }
@@ -251,7 +280,12 @@ module Mongo
251
280
  update_doc['upsert'] = true
252
281
  end
253
282
  with_session(opts) do |session|
254
- write_concern = write_concern_with_session(session)
283
+ write_concern = if opts[:write_concern]
284
+ WriteConcern.get(opts[:write_concern])
285
+ else
286
+ write_concern_with_session(session)
287
+ end
288
+
255
289
  write_with_retry(session, write_concern) do |server, txn_num|
256
290
  apply_collation!(update_doc, server, opts)
257
291
  apply_array_filters!(update_doc, server, opts)
@@ -288,11 +322,15 @@ module Mongo
288
322
  # @option opts [ Session ] :session The session to use.
289
323
  # @option opts [ Hash | String ] :hint The index to use for this operation.
290
324
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
325
+ # @option opts [ Hash ] :write_concern The write concern options.
326
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
291
327
  #
292
328
  # @return [ Result ] The response from the database.
293
329
  #
294
330
  # @since 2.0.0
295
331
  def update_many(spec, opts = {})
332
+ QueryCache.clear_namespace(collection.namespace)
333
+
296
334
  update_doc = { Operation::Q => filter,
297
335
  Operation::U => spec,
298
336
  Operation::MULTI => true,
@@ -301,7 +339,11 @@ module Mongo
301
339
  update_doc['upsert'] = true
302
340
  end
303
341
  with_session(opts) do |session|
304
- write_concern = write_concern_with_session(session)
342
+ write_concern = if opts[:write_concern]
343
+ WriteConcern.get(opts[:write_concern])
344
+ else
345
+ write_concern_with_session(session)
346
+ end
305
347
  nro_write_with_retry(session, write_concern) do |server|
306
348
  apply_collation!(update_doc, server, opts)
307
349
  apply_array_filters!(update_doc, server, opts)
@@ -337,11 +379,15 @@ module Mongo
337
379
  # @option opts [ Session ] :session The session to use.
338
380
  # @option opts [ Hash | String ] :hint The index to use for this operation.
339
381
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
382
+ # @option opts [ Hash ] :write_concern The write concern options.
383
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
340
384
  #
341
385
  # @return [ Result ] The response from the database.
342
386
  #
343
387
  # @since 2.0.0
344
388
  def update_one(spec, opts = {})
389
+ QueryCache.clear_namespace(collection.namespace)
390
+
345
391
  update_doc = { Operation::Q => filter,
346
392
  Operation::U => spec,
347
393
  }
@@ -349,7 +395,11 @@ module Mongo
349
395
  update_doc['upsert'] = true
350
396
  end
351
397
  with_session(opts) do |session|
352
- write_concern = write_concern_with_session(session)
398
+ write_concern = if opts[:write_concern]
399
+ WriteConcern.get(opts[:write_concern])
400
+ else
401
+ write_concern_with_session(session)
402
+ end
353
403
  write_with_retry(session, write_concern) do |server, txn_num|
354
404
  apply_collation!(update_doc, server, opts)
355
405
  apply_array_filters!(update_doc, server, opts)