mongo 2.15.0 → 2.17.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 (393) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/lib/mongo/auth/aws/request.rb +0 -1
  5. data/lib/mongo/bulk_write.rb +2 -2
  6. data/lib/mongo/client.rb +49 -5
  7. data/lib/mongo/cluster/periodic_executor.rb +4 -3
  8. data/lib/mongo/cluster/reapers/cursor_reaper.rb +76 -43
  9. data/lib/mongo/cluster/sdam_flow.rb +9 -3
  10. data/lib/mongo/cluster/topology/base.rb +13 -9
  11. data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
  12. data/lib/mongo/cluster/topology.rb +28 -8
  13. data/lib/mongo/cluster.rb +136 -51
  14. data/lib/mongo/collection/view/aggregation.rb +63 -23
  15. data/lib/mongo/collection/view/builder/aggregation.rb +16 -17
  16. data/lib/mongo/collection/view/builder/map_reduce.rb +12 -49
  17. data/lib/mongo/collection/view/builder.rb +0 -4
  18. data/lib/mongo/collection/view/change_stream.rb +7 -3
  19. data/lib/mongo/collection/view/iterable.rb +60 -27
  20. data/lib/mongo/collection/view/map_reduce.rb +41 -15
  21. data/lib/mongo/collection/view/readable.rb +84 -52
  22. data/lib/mongo/collection/view/writable.rb +201 -175
  23. data/lib/mongo/collection/view.rb +15 -21
  24. data/lib/mongo/collection.rb +34 -14
  25. data/lib/mongo/cursor/kill_spec.rb +38 -0
  26. data/lib/mongo/cursor.rb +72 -31
  27. data/lib/mongo/database/view.rb +5 -3
  28. data/lib/mongo/database.rb +6 -6
  29. data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
  30. data/lib/mongo/error/missing_service_id.rb +26 -0
  31. data/lib/mongo/error/no_service_connection_available.rb +49 -0
  32. data/lib/mongo/error/notable.rb +7 -0
  33. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
  34. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
  35. data/lib/mongo/error.rb +5 -0
  36. data/lib/mongo/grid/fs_bucket.rb +21 -2
  37. data/lib/mongo/id.rb +7 -5
  38. data/lib/mongo/index/view.rb +22 -41
  39. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +7 -4
  40. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  41. data/lib/mongo/monitoring/event/command_started.rb +2 -0
  42. data/lib/mongo/monitoring/publishable.rb +2 -2
  43. data/lib/mongo/operation/aggregate/command.rb +8 -0
  44. data/lib/mongo/operation/context.rb +19 -1
  45. data/lib/mongo/operation/count/command.rb +6 -0
  46. data/lib/mongo/operation/count/op_msg.rb +6 -0
  47. data/lib/mongo/operation/create/command.rb +7 -1
  48. data/lib/mongo/operation/create/op_msg.rb +7 -0
  49. data/lib/mongo/operation/create_index/command.rb +17 -1
  50. data/lib/mongo/operation/create_index/op_msg.rb +17 -4
  51. data/lib/mongo/operation/delete/command.rb +6 -3
  52. data/lib/mongo/operation/delete/legacy.rb +9 -2
  53. data/lib/mongo/operation/delete/op_msg.rb +9 -1
  54. data/lib/mongo/operation/distinct/command.rb +6 -0
  55. data/lib/mongo/operation/distinct/op_msg.rb +7 -0
  56. data/lib/mongo/operation/explain/command.rb +13 -1
  57. data/lib/mongo/operation/explain/legacy.rb +12 -5
  58. data/lib/mongo/operation/explain/op_msg.rb +9 -1
  59. data/lib/mongo/operation/find/builder/command.rb +111 -0
  60. data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +10 -14
  61. data/lib/mongo/operation/find/builder/legacy.rb +123 -0
  62. data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +31 -25
  63. data/lib/mongo/{cursor → operation/find}/builder.rb +4 -4
  64. data/lib/mongo/operation/find/command.rb +9 -0
  65. data/lib/mongo/operation/find/legacy.rb +10 -1
  66. data/lib/mongo/operation/find/op_msg.rb +12 -0
  67. data/lib/mongo/operation/find.rb +1 -0
  68. data/lib/mongo/operation/get_more/command.rb +1 -0
  69. data/lib/mongo/operation/get_more/command_builder.rb +38 -0
  70. data/lib/mongo/operation/get_more/op_msg.rb +1 -0
  71. data/lib/mongo/operation/get_more.rb +1 -0
  72. data/lib/mongo/operation/kill_cursors/command.rb +8 -0
  73. data/lib/mongo/operation/kill_cursors/command_builder.rb +35 -0
  74. data/lib/mongo/operation/kill_cursors/legacy.rb +2 -1
  75. data/lib/mongo/operation/kill_cursors/op_msg.rb +10 -0
  76. data/lib/mongo/operation/kill_cursors.rb +1 -0
  77. data/lib/mongo/operation/map_reduce/command.rb +8 -0
  78. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  79. data/lib/mongo/operation/result.rb +6 -0
  80. data/lib/mongo/operation/shared/executable.rb +19 -1
  81. data/lib/mongo/operation/shared/polymorphic_operation.rb +1 -1
  82. data/lib/mongo/operation/shared/read_preference_supported.rb +3 -1
  83. data/lib/mongo/operation/shared/response_handling.rb +1 -0
  84. data/lib/mongo/operation/shared/sessions_supported.rb +28 -12
  85. data/lib/mongo/operation/shared/specifiable.rb +11 -29
  86. data/lib/mongo/operation/shared/validatable.rb +87 -0
  87. data/lib/mongo/operation/shared/write.rb +1 -1
  88. data/lib/mongo/operation/update/command.rb +6 -3
  89. data/lib/mongo/operation/update/legacy.rb +19 -11
  90. data/lib/mongo/operation/update/op_msg.rb +8 -4
  91. data/lib/mongo/operation/write_command/command.rb +51 -0
  92. data/lib/mongo/operation/write_command/op_msg.rb +43 -0
  93. data/lib/mongo/operation/write_command.rb +32 -0
  94. data/lib/mongo/operation.rb +10 -0
  95. data/lib/mongo/protocol/query.rb +35 -18
  96. data/lib/mongo/server/connection.rb +25 -3
  97. data/lib/mongo/server/connection_base.rb +12 -1
  98. data/lib/mongo/server/connection_common.rb +38 -1
  99. data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
  100. data/lib/mongo/server/connection_pool.rb +100 -27
  101. data/lib/mongo/server/description/features.rb +20 -17
  102. data/lib/mongo/server/description/load_balancer.rb +33 -0
  103. data/lib/mongo/server/description.rb +85 -6
  104. data/lib/mongo/server/monitor/connection.rb +5 -6
  105. data/lib/mongo/server/monitor.rb +2 -1
  106. data/lib/mongo/server/pending_connection.rb +47 -31
  107. data/lib/mongo/server/push_monitor.rb +10 -1
  108. data/lib/mongo/server.rb +73 -26
  109. data/lib/mongo/server_selector/base.rb +31 -5
  110. data/lib/mongo/session/session_pool.rb +11 -0
  111. data/lib/mongo/session.rb +40 -1
  112. data/lib/mongo/socket/ocsp_cache.rb +2 -3
  113. data/lib/mongo/socket/ocsp_verifier.rb +6 -37
  114. data/lib/mongo/socket.rb +1 -5
  115. data/lib/mongo/uri/options_mapper.rb +1 -0
  116. data/lib/mongo/uri/srv_protocol.rb +6 -8
  117. data/lib/mongo/uri.rb +18 -0
  118. data/lib/mongo/utils.rb +0 -13
  119. data/lib/mongo/version.rb +1 -1
  120. data/mongo.gemspec +1 -1
  121. data/spec/integration/auth_spec.rb +31 -1
  122. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  123. data/spec/integration/bulk_write_spec.rb +1 -1
  124. data/spec/integration/change_stream_spec.rb +3 -3
  125. data/spec/integration/client_construction_spec.rb +54 -0
  126. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  127. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  128. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  129. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  130. data/spec/integration/client_spec.rb +2 -0
  131. data/spec/integration/command_monitoring_spec.rb +1 -1
  132. data/spec/integration/command_spec.rb +1 -1
  133. data/spec/integration/connection_spec.rb +52 -35
  134. data/spec/integration/crud_spec.rb +174 -1
  135. data/spec/integration/cursor_pinning_spec.rb +121 -0
  136. data/spec/integration/cursor_reaping_spec.rb +8 -4
  137. data/spec/integration/fork_reconnect_spec.rb +1 -5
  138. data/spec/integration/get_more_spec.rb +1 -1
  139. data/spec/integration/heartbeat_events_spec.rb +1 -1
  140. data/spec/integration/map_reduce_spec.rb +77 -0
  141. data/spec/integration/query_cache_spec.rb +47 -2
  142. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  143. data/spec/integration/read_concern_spec.rb +1 -1
  144. data/spec/integration/read_preference_spec.rb +17 -13
  145. data/spec/integration/reconnect_spec.rb +30 -12
  146. data/spec/integration/retryable_errors_spec.rb +1 -1
  147. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  148. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  149. data/spec/integration/sdam_error_handling_spec.rb +5 -3
  150. data/spec/integration/sdam_events_spec.rb +35 -19
  151. data/spec/integration/sdam_prose_spec.rb +1 -1
  152. data/spec/integration/server_monitor_spec.rb +1 -0
  153. data/spec/integration/server_selector_spec.rb +22 -5
  154. data/spec/integration/server_spec.rb +2 -0
  155. data/spec/integration/srv_monitoring_spec.rb +1 -1
  156. data/spec/integration/step_down_spec.rb +1 -1
  157. data/spec/integration/transaction_pinning_spec.rb +120 -0
  158. data/spec/integration/versioned_api_examples_spec.rb +45 -0
  159. data/spec/integration/x509_auth_spec.rb +1 -1
  160. data/spec/lite_spec_helper.rb +1 -2
  161. data/spec/mongo/address/unix_spec.rb +1 -0
  162. data/spec/mongo/auth/cr_spec.rb +2 -3
  163. data/spec/mongo/auth/ldap_spec.rb +2 -3
  164. data/spec/mongo/auth/scram_spec.rb +2 -3
  165. data/spec/mongo/auth/user/view_spec.rb +1 -1
  166. data/spec/mongo/auth/x509_spec.rb +2 -3
  167. data/spec/mongo/bulk_write_spec.rb +3 -3
  168. data/spec/mongo/client_construction_spec.rb +259 -28
  169. data/spec/mongo/client_spec.rb +6 -4
  170. data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
  171. data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
  172. data/spec/mongo/cluster_spec.rb +44 -3
  173. data/spec/mongo/collection/view/aggregation_spec.rb +72 -96
  174. data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
  175. data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
  176. data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
  177. data/spec/mongo/collection/view/map_reduce_spec.rb +15 -2
  178. data/spec/mongo/collection_crud_spec.rb +7 -2
  179. data/spec/mongo/collection_ddl_spec.rb +1 -1
  180. data/spec/mongo/collection_spec.rb +1 -1
  181. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
  182. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
  183. data/spec/mongo/cursor_spec.rb +15 -5
  184. data/spec/mongo/database_spec.rb +15 -15
  185. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  186. data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
  187. data/spec/mongo/grid/stream/write_spec.rb +3 -9
  188. data/spec/mongo/grid/stream_spec.rb +1 -1
  189. data/spec/mongo/index/view_spec.rb +2 -2
  190. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  191. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
  192. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
  193. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  194. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  195. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  196. data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
  197. data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
  198. data/spec/mongo/operation/read_preference_op_msg_spec.rb +26 -1
  199. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  200. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  201. data/spec/mongo/query_cache_spec.rb +6 -2
  202. data/spec/mongo/server/connection_common_spec.rb +62 -11
  203. data/spec/mongo/server/connection_pool_spec.rb +73 -7
  204. data/spec/mongo/server/connection_spec.rb +138 -43
  205. data/spec/mongo/server/description_spec.rb +1 -1
  206. data/spec/mongo/server/monitor/connection_spec.rb +22 -0
  207. data/spec/mongo/server/monitor_spec.rb +4 -3
  208. data/spec/mongo/server/push_monitor_spec.rb +101 -0
  209. data/spec/mongo/server_selector_spec.rb +136 -15
  210. data/spec/mongo/session/session_pool_spec.rb +42 -10
  211. data/spec/mongo/session_transaction_spec.rb +15 -30
  212. data/spec/mongo/socket/ssl_spec.rb +26 -58
  213. data/spec/mongo/socket/unix_spec.rb +1 -0
  214. data/spec/mongo/uri_option_parsing_spec.rb +38 -5
  215. data/spec/mongo/utils_spec.rb +0 -14
  216. data/spec/runners/change_streams/test.rb +1 -1
  217. data/spec/runners/cmap.rb +1 -1
  218. data/spec/runners/connection_string.rb +7 -3
  219. data/spec/runners/crud/operation.rb +5 -3
  220. data/spec/runners/crud/requirement.rb +1 -0
  221. data/spec/runners/crud/verifier.rb +1 -2
  222. data/spec/runners/crud.rb +1 -1
  223. data/spec/runners/sdam.rb +2 -1
  224. data/spec/runners/transactions/test.rb +2 -2
  225. data/spec/runners/unified/assertions.rb +5 -4
  226. data/spec/runners/unified/crud_operations.rb +77 -23
  227. data/spec/runners/unified/ddl_operations.rb +29 -1
  228. data/spec/runners/unified/entity_map.rb +3 -3
  229. data/spec/runners/unified/event_subscriber.rb +2 -2
  230. data/spec/runners/unified/support_operations.rb +16 -3
  231. data/spec/runners/unified/test.rb +18 -3
  232. data/spec/runners/unified.rb +1 -1
  233. data/spec/shared/lib/mrss/cluster_config.rb +6 -1
  234. data/spec/shared/lib/mrss/constraints.rb +11 -5
  235. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  236. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  237. data/spec/shared/share/Dockerfile.erb +5 -4
  238. data/spec/shared/shlib/server.sh +70 -20
  239. data/spec/spec_tests/change_streams_spec.rb +1 -1
  240. data/spec/spec_tests/cmap_spec.rb +4 -1
  241. data/spec/spec_tests/command_monitoring_spec.rb +2 -2
  242. data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
  243. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  244. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  245. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  246. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  247. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  248. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  249. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  250. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  251. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  252. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  253. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  254. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  255. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  256. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  257. data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
  258. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
  259. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
  260. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
  261. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
  262. data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
  263. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
  264. data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
  265. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
  266. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
  267. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
  268. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  269. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  270. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  271. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  272. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
  273. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  274. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  275. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  276. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
  277. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
  278. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
  279. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
  280. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
  281. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
  282. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
  283. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
  284. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
  285. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  288. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  289. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  290. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
  291. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  292. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
  293. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
  294. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  295. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
  296. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  297. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
  298. data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
  299. data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
  300. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
  301. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
  302. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  303. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
  304. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  305. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
  306. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  307. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
  308. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  309. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
  310. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
  311. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
  312. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
  313. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
  314. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
  315. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
  316. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  317. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  318. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  319. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  320. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  321. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
  322. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
  323. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  324. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  325. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  326. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  327. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  328. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  329. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  330. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  331. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  332. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  333. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  334. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  335. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  336. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  337. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  338. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  339. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  340. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  341. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  342. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  343. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  344. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  345. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  346. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  347. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  348. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  349. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
  350. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
  351. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
  352. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
  353. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
  354. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
  355. data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
  356. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
  357. data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
  358. data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
  359. data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
  360. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  361. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  362. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  363. data/spec/spec_tests/sdam_integration_spec.rb +1 -1
  364. data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
  365. data/spec/spec_tests/sdam_spec.rb +1 -1
  366. data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
  367. data/spec/spec_tests/sessions_unified_spec.rb +13 -0
  368. data/spec/spec_tests/uri_options_spec.rb +4 -4
  369. data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
  370. data/spec/stress/push_monitor_close_spec.rb +44 -0
  371. data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
  372. data/spec/support/certificates/atlas-ocsp.crt +127 -122
  373. data/spec/support/common_shortcuts.rb +2 -3
  374. data/spec/support/matchers.rb +13 -0
  375. data/spec/support/shared/auth_context.rb +16 -0
  376. data/spec/support/shared/session.rb +2 -2
  377. data/spec/support/spec_config.rb +10 -11
  378. data/spec/support/using_hash.rb +31 -0
  379. data/spec/support/utils.rb +1 -1
  380. data.tar.gz.sig +3 -4
  381. metadata +1111 -1029
  382. metadata.gz.sig +2 -3
  383. data/lib/mongo/collection/view/builder/find_command.rb +0 -173
  384. data/lib/mongo/collection/view/builder/op_query.rb +0 -94
  385. data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
  386. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
  387. data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
  388. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
  389. data/lib/mongo/server/context.rb +0 -72
  390. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
  391. data/spec/runners/unified/using_hash.rb +0 -34
  392. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
  393. data/spec/support/event_subscriber.rb +0 -221
@@ -46,33 +46,47 @@ module Mongo
46
46
  # @option opts [ Session ] :session The session to use.
47
47
  # @option opts [ Hash | String ] :hint The index to use for this operation.
48
48
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
49
+ # @option opts [ Hash ] :write_concern The write concern options.
50
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
51
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
52
+ # See the server documentation for details.
49
53
  #
50
54
  # @return [ BSON::Document, nil ] The document, if found.
51
55
  #
52
56
  # @since 2.0.0
53
57
  def find_one_and_delete(opts = {})
54
- QueryCache.clear_namespace(collection.namespace)
55
-
56
- cmd = { :findAndModify => collection.name, :query => filter, :remove => true }
57
- cmd[:fields] = projection if projection
58
- cmd[:sort] = sort if sort
59
- cmd[:maxTimeMS] = max_time_ms if max_time_ms
60
- if opts[:bypass_document_validation]
61
- cmd[:bypassDocumentValidation] = true
62
- end
63
-
64
58
  with_session(opts) do |session|
65
- applied_write_concern = applied_write_concern(session)
66
- cmd[:writeConcern] = applied_write_concern.options if applied_write_concern
67
- write_with_retry(session, applied_write_concern) do |server, txn_num|
68
- apply_collation!(cmd, server, opts)
69
- apply_hint!(cmd, server, opts.merge(write_concern: applied_write_concern))
70
-
71
- Operation::Command.new(
72
- :selector => cmd,
73
- :db_name => database.name,
74
- :session => session,
75
- :txn_num => txn_num,
59
+ write_concern = if opts[:write_concern]
60
+ WriteConcern.get(opts[:write_concern])
61
+ else
62
+ write_concern_with_session(session)
63
+ end
64
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
65
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
66
+ end
67
+
68
+ QueryCache.clear_namespace(collection.namespace)
69
+
70
+ cmd = {
71
+ findAndModify: collection.name,
72
+ query: filter,
73
+ remove: true,
74
+ fields: projection,
75
+ sort: sort,
76
+ maxTimeMS: max_time_ms,
77
+ bypassDocumentValidation: opts[:bypass_document_validation],
78
+ hint: opts[:hint],
79
+ collation: opts[:collation] || opts['collation'] || collation,
80
+ let: opts[:let]
81
+ }.compact
82
+
83
+ write_with_retry(session, write_concern) do |server, txn_num|
84
+ Operation::WriteCommand.new(
85
+ selector: cmd,
86
+ db_name: database.name,
87
+ write_concern: write_concern,
88
+ session: session,
89
+ txn_num: txn_num,
76
90
  ).execute(server, context: Operation::Context.new(client: client, session: session))
77
91
  end
78
92
  end.first['value']
@@ -96,6 +110,10 @@ module Mongo
96
110
  # @option opts [ Hash ] :collation The collation to use.
97
111
  # @option opts [ Hash | String ] :hint The index to use for this operation.
98
112
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
113
+ # @option opts [ Hash ] :write_concern The write concern options.
114
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
115
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
116
+ # See the server documentation for details.
99
117
  #
100
118
  # @return [ BSON::Document ] The document.
101
119
  #
@@ -127,37 +145,50 @@ module Mongo
127
145
  # @option opts [ Session ] :session The session to use.
128
146
  # @option opts [ Hash | String ] :hint The index to use for this operation.
129
147
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
148
+ # @option opts [ Hash ] :write_concern The write concern options.
149
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
150
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
151
+ # See the server documentation for details.
130
152
  #
131
153
  # @return [ BSON::Document ] The document.
132
154
  #
133
155
  # @since 2.0.0
134
156
  def find_one_and_update(document, opts = {})
135
- QueryCache.clear_namespace(collection.namespace)
136
-
137
- cmd = { :findAndModify => collection.name, :query => filter }
138
- cmd[:update] = document
139
- cmd[:fields] = projection if projection
140
- cmd[:sort] = sort if sort
141
- cmd[:new] = !!(opts[:return_document] && opts[:return_document] == :after)
142
- cmd[:upsert] = opts[:upsert] if opts[:upsert]
143
- cmd[:maxTimeMS] = max_time_ms if max_time_ms
144
- if opts[:bypass_document_validation]
145
- cmd[:bypassDocumentValidation] = true
146
- end
147
-
148
157
  value = with_session(opts) do |session|
149
- applied_write_concern = applied_write_concern(opts[:session])
150
- cmd[:writeConcern] = applied_write_concern.options if applied_write_concern
151
- write_with_retry(session, applied_write_concern) do |server, txn_num|
152
- apply_collation!(cmd, server, opts)
153
- apply_array_filters!(cmd, server, opts)
154
- apply_hint!(cmd, server, opts.merge(write_concern: applied_write_concern))
155
-
156
- Operation::Command.new(
157
- :selector => cmd,
158
- :db_name => database.name,
159
- :session => session,
160
- :txn_num => txn_num,
158
+ write_concern = if opts[:write_concern]
159
+ WriteConcern.get(opts[:write_concern])
160
+ else
161
+ write_concern_with_session(session)
162
+ end
163
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
164
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
165
+ end
166
+
167
+ QueryCache.clear_namespace(collection.namespace)
168
+
169
+ cmd = {
170
+ findAndModify: collection.name,
171
+ query: filter,
172
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
173
+ update: document,
174
+ fields: projection,
175
+ sort: sort,
176
+ new: !!(opts[:return_document] && opts[:return_document] == :after),
177
+ upsert: opts[:upsert],
178
+ maxTimeMS: max_time_ms,
179
+ bypassDocumentValidation: opts[:bypass_document_validation],
180
+ hint: opts[:hint],
181
+ collation: opts[:collation] || opts['collation'] || collation,
182
+ let: opts[:let],
183
+ }.compact
184
+
185
+ write_with_retry(session, write_concern) do |server, txn_num|
186
+ Operation::WriteCommand.new(
187
+ selector: cmd,
188
+ db_name: database.name,
189
+ write_concern: write_concern,
190
+ session: session,
191
+ txn_num: txn_num,
161
192
  ).execute(server, context: Operation::Context.new(client: client, session: session))
162
193
  end
163
194
  end.first['value']
@@ -177,31 +208,41 @@ module Mongo
177
208
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
178
209
  # @option opts [ Hash ] :write_concern The write concern options.
179
210
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
211
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
212
+ # See the server documentation for details.
180
213
  #
181
214
  # @return [ Result ] The response from the database.
182
215
  #
183
216
  # @since 2.0.0
184
217
  def delete_many(opts = {})
185
- QueryCache.clear_namespace(collection.namespace)
186
-
187
- delete_doc = { Operation::Q => filter, Operation::LIMIT => 0 }
188
218
  with_session(opts) do |session|
189
219
  write_concern = if opts[:write_concern]
190
220
  WriteConcern.get(opts[:write_concern])
191
221
  else
192
222
  write_concern_with_session(session)
193
223
  end
194
- nro_write_with_retry(session, write_concern) do |server|
195
- apply_collation!(delete_doc, server, opts)
196
- apply_hint!(delete_doc, server, opts.merge(write_concern: write_concern))
224
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
225
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
226
+ end
227
+
228
+ QueryCache.clear_namespace(collection.namespace)
229
+
230
+ delete_doc = {
231
+ Operation::Q => filter,
232
+ Operation::LIMIT => 0,
233
+ hint: opts[:hint],
234
+ collation: opts[:collation] || opts['collation'] || collation,
235
+ }.compact
197
236
 
237
+ nro_write_with_retry(session, write_concern) do |server|
198
238
  Operation::Delete.new(
199
- :deletes => [ delete_doc ],
200
- :db_name => collection.database.name,
201
- :coll_name => collection.name,
202
- :write_concern => write_concern,
203
- :bypass_document_validation => !!opts[:bypass_document_validation],
204
- :session => session,
239
+ deletes: [ delete_doc ],
240
+ db_name: collection.database.name,
241
+ coll_name: collection.name,
242
+ write_concern: write_concern,
243
+ bypass_document_validation: !!opts[:bypass_document_validation],
244
+ session: session,
245
+ let: opts[:let],
205
246
  ).execute(server, context: Operation::Context.new(client: client, session: session))
206
247
  end
207
248
  end
@@ -220,32 +261,42 @@ module Mongo
220
261
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
221
262
  # @option opts [ Hash ] :write_concern The write concern options.
222
263
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
264
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
265
+ # See the server documentation for details.
223
266
  #
224
267
  # @return [ Result ] The response from the database.
225
268
  #
226
269
  # @since 2.0.0
227
270
  def delete_one(opts = {})
228
- QueryCache.clear_namespace(collection.namespace)
229
-
230
- delete_doc = { Operation::Q => filter, Operation::LIMIT => 1 }
231
271
  with_session(opts) do |session|
232
272
  write_concern = if opts[:write_concern]
233
273
  WriteConcern.get(opts[:write_concern])
234
274
  else
235
275
  write_concern_with_session(session)
236
276
  end
237
- write_with_retry(session, write_concern) do |server, txn_num|
238
- apply_collation!(delete_doc, server, opts)
239
- apply_hint!(delete_doc, server, opts.merge(write_concern: write_concern))
277
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
278
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
279
+ end
280
+
281
+ QueryCache.clear_namespace(collection.namespace)
282
+
283
+ delete_doc = {
284
+ Operation::Q => filter,
285
+ Operation::LIMIT => 1,
286
+ hint: opts[:hint],
287
+ collation: opts[:collation] || opts['collation'] || collation,
288
+ }.compact
240
289
 
290
+ write_with_retry(session, write_concern) do |server, txn_num|
241
291
  Operation::Delete.new(
242
- :deletes => [ delete_doc ],
243
- :db_name => collection.database.name,
244
- :coll_name => collection.name,
245
- :write_concern => write_concern,
246
- :bypass_document_validation => !!opts[:bypass_document_validation],
247
- :session => session,
248
- :txn_num => txn_num,
292
+ deletes: [ delete_doc ],
293
+ db_name: collection.database.name,
294
+ coll_name: collection.name,
295
+ write_concern: write_concern,
296
+ bypass_document_validation: !!opts[:bypass_document_validation],
297
+ session: session,
298
+ txn_num: txn_num,
299
+ let: opts[:let],
249
300
  ).execute(server, context: Operation::Context.new(client: client, session: session))
250
301
  end
251
302
  end
@@ -269,39 +320,46 @@ module Mongo
269
320
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
270
321
  # @option opts [ Hash ] :write_concern The write concern options.
271
322
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
323
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
324
+ # See the server documentation for details.
272
325
  #
273
326
  # @return [ Result ] The response from the database.
274
327
  #
275
328
  # @since 2.0.0
276
329
  def replace_one(replacement, opts = {})
277
- QueryCache.clear_namespace(collection.namespace)
278
-
279
- update_doc = { Operation::Q => filter,
280
- Operation::U => replacement,
281
- }
282
- if opts[:upsert]
283
- update_doc['upsert'] = true
284
- end
285
330
  with_session(opts) do |session|
286
331
  write_concern = if opts[:write_concern]
287
332
  WriteConcern.get(opts[:write_concern])
288
333
  else
289
334
  write_concern_with_session(session)
290
335
  end
336
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
337
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
338
+ end
291
339
 
292
- write_with_retry(session, write_concern) do |server, txn_num|
293
- apply_collation!(update_doc, server, opts)
294
- apply_array_filters!(update_doc, server, opts)
295
- apply_hint!(update_doc, server, opts.merge(write_concern: write_concern))
340
+ QueryCache.clear_namespace(collection.namespace)
341
+
342
+ update_doc = {
343
+ Operation::Q => filter,
344
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
345
+ Operation::U => replacement,
346
+ hint: opts[:hint],
347
+ collation: opts[:collation] || opts['collation'] || collation,
348
+ }.compact
349
+ if opts[:upsert]
350
+ update_doc['upsert'] = true
351
+ end
296
352
 
353
+ write_with_retry(session, write_concern) do |server, txn_num|
297
354
  Operation::Update.new(
298
- :updates => [ update_doc ],
299
- :db_name => collection.database.name,
300
- :coll_name => collection.name,
301
- :write_concern => write_concern,
302
- :bypass_document_validation => !!opts[:bypass_document_validation],
303
- :session => session,
304
- :txn_num => txn_num,
355
+ updates: [ update_doc ],
356
+ db_name: collection.database.name,
357
+ coll_name: collection.name,
358
+ write_concern: write_concern,
359
+ bypass_document_validation: !!opts[:bypass_document_validation],
360
+ session: session,
361
+ txn_num: txn_num,
362
+ let: opts[:let]
305
363
  ).execute(server, context: Operation::Context.new(client: client, session: session))
306
364
  end
307
365
  end
@@ -327,38 +385,46 @@ module Mongo
327
385
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
328
386
  # @option opts [ Hash ] :write_concern The write concern options.
329
387
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
388
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
389
+ # See the server documentation for details.
330
390
  #
331
391
  # @return [ Result ] The response from the database.
332
392
  #
333
393
  # @since 2.0.0
334
394
  def update_many(spec, opts = {})
335
- QueryCache.clear_namespace(collection.namespace)
336
-
337
- update_doc = { Operation::Q => filter,
338
- Operation::U => spec,
339
- Operation::MULTI => true,
340
- }
341
- if opts[:upsert]
342
- update_doc['upsert'] = true
343
- end
344
395
  with_session(opts) do |session|
345
396
  write_concern = if opts[:write_concern]
346
397
  WriteConcern.get(opts[:write_concern])
347
398
  else
348
399
  write_concern_with_session(session)
349
400
  end
350
- nro_write_with_retry(session, write_concern) do |server|
351
- apply_collation!(update_doc, server, opts)
352
- apply_array_filters!(update_doc, server, opts)
353
- apply_hint!(update_doc, server, opts.merge(write_concern: write_concern))
401
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
402
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
403
+ end
404
+
405
+ QueryCache.clear_namespace(collection.namespace)
406
+
407
+ update_doc = {
408
+ Operation::Q => filter,
409
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
410
+ Operation::U => spec,
411
+ Operation::MULTI => true,
412
+ hint: opts[:hint],
413
+ collation: opts[:collation] || opts['collation'] || collation,
414
+ }.compact
415
+ if opts[:upsert]
416
+ update_doc['upsert'] = true
417
+ end
354
418
 
419
+ nro_write_with_retry(session, write_concern) do |server|
355
420
  Operation::Update.new(
356
- :updates => [ update_doc ],
357
- :db_name => collection.database.name,
358
- :coll_name => collection.name,
359
- :write_concern => write_concern,
360
- :bypass_document_validation => !!opts[:bypass_document_validation],
361
- :session => session,
421
+ updates: [ update_doc ],
422
+ db_name: collection.database.name,
423
+ coll_name: collection.name,
424
+ write_concern: write_concern,
425
+ bypass_document_validation: !!opts[:bypass_document_validation],
426
+ session: session,
427
+ let: opts[:let],
362
428
  ).execute(server, context: Operation::Context.new(client: client, session: session))
363
429
  end
364
430
  end
@@ -384,88 +450,48 @@ module Mongo
384
450
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
385
451
  # @option opts [ Hash ] :write_concern The write concern options.
386
452
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
453
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
454
+ # See the server documentation for details.
387
455
  #
388
456
  # @return [ Result ] The response from the database.
389
457
  #
390
458
  # @since 2.0.0
391
459
  def update_one(spec, opts = {})
392
- QueryCache.clear_namespace(collection.namespace)
393
-
394
- update_doc = { Operation::Q => filter,
395
- Operation::U => spec,
396
- }
397
- if opts[:upsert]
398
- update_doc['upsert'] = true
399
- end
400
460
  with_session(opts) do |session|
401
461
  write_concern = if opts[:write_concern]
402
462
  WriteConcern.get(opts[:write_concern])
403
463
  else
404
464
  write_concern_with_session(session)
405
465
  end
406
- write_with_retry(session, write_concern) do |server, txn_num|
407
- apply_collation!(update_doc, server, opts)
408
- apply_array_filters!(update_doc, server, opts)
409
- apply_hint!(update_doc, server, opts.merge(write_concern: write_concern))
410
-
411
- Operation::Update.new(
412
- :updates => [ update_doc ],
413
- :db_name => collection.database.name,
414
- :coll_name => collection.name,
415
- :write_concern => write_concern,
416
- :bypass_document_validation => !!opts[:bypass_document_validation],
417
- :session => session,
418
- :txn_num => txn_num,
419
- ).execute(server, context: Operation::Context.new(client: client, session: session))
420
- end
421
- end
422
- end
423
-
424
- private
425
-
426
- def apply_hint!(doc, server, opts)
427
- if hint = opts[:hint]
428
- features = server.with_connection do |connection|
429
- connection.description.features
430
- end
431
-
432
- write_concern = opts[:write_concern]
433
- if write_concern && !write_concern.acknowledged?
466
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
434
467
  raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
435
468
  end
436
469
 
437
- if doc.key?(:findAndModify) &&
438
- !features.find_and_modify_option_validation_enabled?
439
- raise Error::UnsupportedOption.hint_error
440
- elsif !features.update_delete_option_validation_enabled?
441
- raise Error::UnsupportedOption.hint_error
470
+ QueryCache.clear_namespace(collection.namespace)
471
+
472
+ update_doc = {
473
+ Operation::Q => filter,
474
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
475
+ Operation::U => spec,
476
+ hint: opts[:hint],
477
+ collation: opts[:collation] || opts['collation'] || collation,
478
+ }.compact
479
+ if opts[:upsert]
480
+ update_doc['upsert'] = true
442
481
  end
443
482
 
444
- doc[:hint] = opts[:hint]
445
- end
446
- end
447
-
448
- def apply_array_filters!(doc, server, opts = {})
449
- if filters = opts[:array_filters] || opts[ARRAY_FILTERS]
450
- validate_array_filters!(server, filters)
451
- doc[:arrayFilters] = filters
452
- end
453
- end
454
-
455
- def validate_array_filters!(server, filters)
456
- if filters && !server.with_connection { |connection| connection.features }.array_filters_enabled?
457
- raise Error::UnsupportedArrayFilters.new
458
- end
459
- end
460
-
461
- # Get the write concern for an operation
462
- #
463
- # @return [ Mongo::WriteConcern ] The write concern.
464
- def applied_write_concern(session)
465
- if wco = options[:write_concern] || options[:write]
466
- WriteConcern.get(wco)
467
- else
468
- write_concern_with_session(session)
483
+ write_with_retry(session, write_concern) do |server, txn_num|
484
+ Operation::Update.new(
485
+ updates: [ update_doc ],
486
+ db_name: collection.database.name,
487
+ coll_name: collection.name,
488
+ write_concern: write_concern,
489
+ bypass_document_validation: !!opts[:bypass_document_validation],
490
+ session: session,
491
+ txn_num: txn_num,
492
+ let: opts[:let],
493
+ ).execute(server, context: Operation::Context.new(client: client, session: session))
494
+ end
469
495
  end
470
496
  end
471
497
  end
@@ -141,6 +141,8 @@ module Mongo
141
141
  # @option options [ Hash ] :read The read preference to use for the
142
142
  # query. If none is provided, the collection's default read preference
143
143
  # is used.
144
+ # @option options [ Hash ] :read_concern The read concern to use for
145
+ # the query.
144
146
  # @option options [ true | false ] :show_disk_loc Return disk location
145
147
  # info as a field in each doc.
146
148
  # @option options [ Integer ] :skip The number of documents to skip.
@@ -153,7 +155,19 @@ module Mongo
153
155
  def initialize(collection, filter = {}, options = {})
154
156
  validate_doc!(filter)
155
157
  @collection = collection
156
- parse_parameters!(BSON::Document.new(filter), BSON::Document.new(options))
158
+
159
+ filter = BSON::Document.new(filter)
160
+ options = BSON::Document.new(options)
161
+
162
+ # This is when users pass $query in filter and other modifiers
163
+ # alongside?
164
+ query = filter.delete(:$query)
165
+ # This makes modifiers contain the filter if filter wasn't
166
+ # given via $query but as top-level keys, presumably
167
+ # downstream code ignores non-modifier keys in the modifiers?
168
+ modifiers = filter.merge(options.delete(:modifiers) || {})
169
+ @filter = (query || filter).freeze
170
+ @options = Operation::Find::Builder::Modifiers.map_driver_options(modifiers).merge!(options).freeze
157
171
  end
158
172
 
159
173
  # Get a human-readable string representation of +View+.
@@ -189,30 +203,10 @@ module Mongo
189
203
  @filter = other.filter.dup
190
204
  end
191
205
 
192
- def parse_parameters!(filter, options)
193
- query = filter.delete(QUERY)
194
- modifiers = (filter || {}).merge(options.delete(MODIFIERS) || {})
195
- @filter = (query || filter).freeze
196
- @options = Builder::Modifiers.map_driver_options(modifiers).merge!(options).freeze
197
- end
198
-
199
206
  def new(options)
200
207
  View.new(collection, filter, options)
201
208
  end
202
209
 
203
- def apply_collation!(doc, server, opts = {})
204
- if coll = doc[:collation] || opts[:collation] || opts['collation'] || collation
205
- validate_collation!(server, coll)
206
- doc[:collation] = coll
207
- end
208
- end
209
-
210
- def validate_collation!(server, coll)
211
- if coll && !server.with_connection { |connection| connection.features }.collation_enabled?
212
- raise Error::UnsupportedCollation.new
213
- end
214
- end
215
-
216
210
  def view; self; end
217
211
 
218
212
  def with_session(opts = {}, &block)