mongo 2.15.1 → 2.16.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (326) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/lib/mongo/bulk_write.rb +2 -2
  5. data/lib/mongo/client.rb +45 -5
  6. data/lib/mongo/cluster/periodic_executor.rb +4 -3
  7. data/lib/mongo/cluster/reapers/cursor_reaper.rb +76 -43
  8. data/lib/mongo/cluster/sdam_flow.rb +9 -3
  9. data/lib/mongo/cluster/topology/base.rb +13 -9
  10. data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
  11. data/lib/mongo/cluster/topology.rb +28 -8
  12. data/lib/mongo/cluster.rb +136 -51
  13. data/lib/mongo/collection/view/aggregation.rb +5 -10
  14. data/lib/mongo/collection/view/builder/aggregation.rb +6 -5
  15. data/lib/mongo/collection/view/builder/map_reduce.rb +12 -49
  16. data/lib/mongo/collection/view/builder.rb +0 -4
  17. data/lib/mongo/collection/view/iterable.rb +42 -18
  18. data/lib/mongo/collection/view/map_reduce.rb +39 -15
  19. data/lib/mongo/collection/view/readable.rb +60 -51
  20. data/lib/mongo/collection/view/writable.rb +178 -175
  21. data/lib/mongo/collection/view.rb +15 -21
  22. data/lib/mongo/collection.rb +13 -13
  23. data/lib/mongo/cursor/kill_spec.rb +38 -0
  24. data/lib/mongo/cursor.rb +62 -31
  25. data/lib/mongo/database/view.rb +1 -1
  26. data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
  27. data/lib/mongo/error/missing_service_id.rb +26 -0
  28. data/lib/mongo/error/no_service_connection_available.rb +49 -0
  29. data/lib/mongo/error/notable.rb +7 -0
  30. data/lib/mongo/error.rb +3 -0
  31. data/lib/mongo/grid/fs_bucket.rb +21 -2
  32. data/lib/mongo/id.rb +7 -5
  33. data/lib/mongo/index/view.rb +22 -41
  34. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +7 -4
  35. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  36. data/lib/mongo/monitoring/event/command_started.rb +2 -0
  37. data/lib/mongo/monitoring/publishable.rb +2 -2
  38. data/lib/mongo/operation/aggregate/command.rb +8 -0
  39. data/lib/mongo/operation/context.rb +19 -1
  40. data/lib/mongo/operation/count/command.rb +6 -0
  41. data/lib/mongo/operation/count/op_msg.rb +6 -0
  42. data/lib/mongo/operation/create/command.rb +7 -1
  43. data/lib/mongo/operation/create/op_msg.rb +7 -0
  44. data/lib/mongo/operation/create_index/command.rb +17 -1
  45. data/lib/mongo/operation/create_index/op_msg.rb +17 -4
  46. data/lib/mongo/operation/delete/command.rb +6 -3
  47. data/lib/mongo/operation/delete/legacy.rb +9 -2
  48. data/lib/mongo/operation/delete/op_msg.rb +8 -1
  49. data/lib/mongo/operation/distinct/command.rb +6 -0
  50. data/lib/mongo/operation/distinct/op_msg.rb +7 -0
  51. data/lib/mongo/operation/explain/command.rb +13 -1
  52. data/lib/mongo/operation/explain/legacy.rb +12 -5
  53. data/lib/mongo/operation/explain/op_msg.rb +9 -1
  54. data/lib/mongo/operation/find/builder/command.rb +110 -0
  55. data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +10 -14
  56. data/lib/mongo/operation/find/builder/legacy.rb +123 -0
  57. data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +31 -25
  58. data/lib/mongo/{cursor → operation/find}/builder.rb +4 -4
  59. data/lib/mongo/operation/find/command.rb +9 -0
  60. data/lib/mongo/operation/find/legacy.rb +10 -1
  61. data/lib/mongo/operation/find/op_msg.rb +12 -0
  62. data/lib/mongo/operation/find.rb +1 -0
  63. data/lib/mongo/operation/get_more/command.rb +1 -0
  64. data/lib/mongo/operation/get_more/command_builder.rb +38 -0
  65. data/lib/mongo/operation/get_more/op_msg.rb +1 -0
  66. data/lib/mongo/operation/get_more.rb +1 -0
  67. data/lib/mongo/operation/kill_cursors/command.rb +8 -0
  68. data/lib/mongo/operation/kill_cursors/command_builder.rb +35 -0
  69. data/lib/mongo/operation/kill_cursors/legacy.rb +2 -1
  70. data/lib/mongo/operation/kill_cursors/op_msg.rb +10 -0
  71. data/lib/mongo/operation/kill_cursors.rb +1 -0
  72. data/lib/mongo/operation/map_reduce/command.rb +8 -0
  73. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  74. data/lib/mongo/operation/shared/executable.rb +15 -1
  75. data/lib/mongo/operation/shared/polymorphic_operation.rb +1 -1
  76. data/lib/mongo/operation/shared/read_preference_supported.rb +3 -1
  77. data/lib/mongo/operation/shared/response_handling.rb +1 -0
  78. data/lib/mongo/operation/shared/sessions_supported.rb +12 -12
  79. data/lib/mongo/operation/shared/specifiable.rb +11 -29
  80. data/lib/mongo/operation/shared/validatable.rb +87 -0
  81. data/lib/mongo/operation/shared/write.rb +1 -1
  82. data/lib/mongo/operation/update/command.rb +6 -3
  83. data/lib/mongo/operation/update/legacy.rb +19 -11
  84. data/lib/mongo/operation/update/op_msg.rb +7 -4
  85. data/lib/mongo/operation/write_command/command.rb +51 -0
  86. data/lib/mongo/operation/write_command/op_msg.rb +43 -0
  87. data/lib/mongo/operation/write_command.rb +32 -0
  88. data/lib/mongo/operation.rb +10 -0
  89. data/lib/mongo/protocol/query.rb +35 -18
  90. data/lib/mongo/server/connection.rb +25 -3
  91. data/lib/mongo/server/connection_base.rb +12 -1
  92. data/lib/mongo/server/connection_common.rb +38 -1
  93. data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
  94. data/lib/mongo/server/connection_pool.rb +100 -27
  95. data/lib/mongo/server/description/features.rb +17 -16
  96. data/lib/mongo/server/description/load_balancer.rb +33 -0
  97. data/lib/mongo/server/description.rb +85 -6
  98. data/lib/mongo/server/monitor/connection.rb +5 -6
  99. data/lib/mongo/server/monitor.rb +2 -1
  100. data/lib/mongo/server/pending_connection.rb +47 -31
  101. data/lib/mongo/server.rb +73 -26
  102. data/lib/mongo/server_selector/base.rb +5 -1
  103. data/lib/mongo/session/session_pool.rb +11 -0
  104. data/lib/mongo/session.rb +21 -1
  105. data/lib/mongo/socket/ocsp_verifier.rb +6 -37
  106. data/lib/mongo/uri/options_mapper.rb +1 -0
  107. data/lib/mongo/uri/srv_protocol.rb +6 -8
  108. data/lib/mongo/uri.rb +18 -0
  109. data/lib/mongo/utils.rb +0 -7
  110. data/lib/mongo/version.rb +1 -1
  111. data/mongo.gemspec +1 -1
  112. data/spec/integration/auth_spec.rb +31 -1
  113. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  114. data/spec/integration/bulk_write_spec.rb +1 -1
  115. data/spec/integration/change_stream_spec.rb +3 -3
  116. data/spec/integration/client_construction_spec.rb +54 -0
  117. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  118. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  119. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  120. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  121. data/spec/integration/client_spec.rb +2 -0
  122. data/spec/integration/command_monitoring_spec.rb +1 -1
  123. data/spec/integration/command_spec.rb +1 -1
  124. data/spec/integration/connection_spec.rb +52 -35
  125. data/spec/integration/crud_spec.rb +174 -1
  126. data/spec/integration/cursor_pinning_spec.rb +121 -0
  127. data/spec/integration/cursor_reaping_spec.rb +8 -4
  128. data/spec/integration/fork_reconnect_spec.rb +1 -5
  129. data/spec/integration/get_more_spec.rb +1 -1
  130. data/spec/integration/heartbeat_events_spec.rb +1 -1
  131. data/spec/integration/map_reduce_spec.rb +77 -0
  132. data/spec/integration/query_cache_spec.rb +2 -2
  133. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  134. data/spec/integration/read_concern_spec.rb +1 -1
  135. data/spec/integration/read_preference_spec.rb +1 -1
  136. data/spec/integration/reconnect_spec.rb +30 -12
  137. data/spec/integration/retryable_errors_spec.rb +1 -1
  138. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  139. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  140. data/spec/integration/sdam_error_handling_spec.rb +5 -3
  141. data/spec/integration/sdam_events_spec.rb +35 -19
  142. data/spec/integration/sdam_prose_spec.rb +1 -1
  143. data/spec/integration/server_monitor_spec.rb +1 -0
  144. data/spec/integration/server_selector_spec.rb +22 -5
  145. data/spec/integration/server_spec.rb +2 -0
  146. data/spec/integration/srv_monitoring_spec.rb +1 -1
  147. data/spec/integration/step_down_spec.rb +1 -1
  148. data/spec/integration/transaction_pinning_spec.rb +120 -0
  149. data/spec/integration/versioned_api_examples_spec.rb +45 -0
  150. data/spec/integration/x509_auth_spec.rb +1 -1
  151. data/spec/lite_spec_helper.rb +1 -2
  152. data/spec/mongo/address/unix_spec.rb +1 -0
  153. data/spec/mongo/auth/cr_spec.rb +2 -3
  154. data/spec/mongo/auth/ldap_spec.rb +2 -3
  155. data/spec/mongo/auth/scram_spec.rb +2 -3
  156. data/spec/mongo/auth/user/view_spec.rb +1 -1
  157. data/spec/mongo/auth/x509_spec.rb +2 -3
  158. data/spec/mongo/bulk_write_spec.rb +3 -3
  159. data/spec/mongo/client_construction_spec.rb +259 -28
  160. data/spec/mongo/client_spec.rb +6 -4
  161. data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
  162. data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
  163. data/spec/mongo/cluster_spec.rb +44 -3
  164. data/spec/mongo/collection/view/aggregation_spec.rb +1 -1
  165. data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
  166. data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
  167. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  168. data/spec/mongo/collection_crud_spec.rb +7 -2
  169. data/spec/mongo/collection_ddl_spec.rb +1 -1
  170. data/spec/mongo/collection_spec.rb +1 -1
  171. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
  172. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
  173. data/spec/mongo/cursor_spec.rb +15 -5
  174. data/spec/mongo/database_spec.rb +15 -15
  175. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  176. data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
  177. data/spec/mongo/grid/stream/write_spec.rb +3 -9
  178. data/spec/mongo/grid/stream_spec.rb +1 -1
  179. data/spec/mongo/index/view_spec.rb +2 -2
  180. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  181. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
  182. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
  183. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  184. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  185. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  186. data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
  187. data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
  188. data/spec/mongo/operation/read_preference_op_msg_spec.rb +2 -0
  189. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  190. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  191. data/spec/mongo/query_cache_spec.rb +6 -2
  192. data/spec/mongo/server/connection_common_spec.rb +62 -11
  193. data/spec/mongo/server/connection_pool_spec.rb +73 -7
  194. data/spec/mongo/server/connection_spec.rb +138 -43
  195. data/spec/mongo/server/description_spec.rb +1 -1
  196. data/spec/mongo/server/monitor_spec.rb +4 -3
  197. data/spec/mongo/session/session_pool_spec.rb +42 -10
  198. data/spec/mongo/session_transaction_spec.rb +15 -30
  199. data/spec/mongo/socket/unix_spec.rb +1 -0
  200. data/spec/mongo/uri_option_parsing_spec.rb +38 -5
  201. data/spec/runners/change_streams/test.rb +1 -1
  202. data/spec/runners/cmap.rb +1 -1
  203. data/spec/runners/connection_string.rb +7 -3
  204. data/spec/runners/crud/operation.rb +5 -3
  205. data/spec/runners/crud/requirement.rb +1 -0
  206. data/spec/runners/crud.rb +1 -1
  207. data/spec/runners/sdam.rb +2 -1
  208. data/spec/runners/transactions/test.rb +2 -2
  209. data/spec/runners/unified/assertions.rb +2 -3
  210. data/spec/runners/unified/event_subscriber.rb +2 -2
  211. data/spec/runners/unified/test.rb +3 -0
  212. data/spec/runners/unified.rb +1 -1
  213. data/spec/shared/lib/mrss/constraints.rb +11 -5
  214. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  215. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  216. data/spec/shared/share/Dockerfile.erb +2 -1
  217. data/spec/shared/shlib/server.sh +70 -20
  218. data/spec/spec_tests/change_streams_spec.rb +1 -1
  219. data/spec/spec_tests/cmap_spec.rb +4 -1
  220. data/spec/spec_tests/command_monitoring_spec.rb +2 -2
  221. data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
  222. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  223. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  224. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  225. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  226. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  227. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  228. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  229. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  230. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  231. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  232. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  233. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  234. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  235. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  236. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  237. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  238. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  239. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  240. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
  241. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  242. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
  243. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  244. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
  245. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  246. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
  247. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  248. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
  249. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
  250. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
  251. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
  252. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
  253. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
  254. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
  255. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  256. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  257. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  258. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  259. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  260. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
  261. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
  262. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  263. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  264. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  265. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  266. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  267. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  268. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  269. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  270. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  271. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  272. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  273. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  274. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  275. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  276. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  277. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  278. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  279. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  280. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  281. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  282. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  283. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  284. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  285. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  286. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  287. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  288. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
  289. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
  290. data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
  291. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
  292. data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
  293. data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
  294. data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
  295. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  296. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  297. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  298. data/spec/spec_tests/sdam_integration_spec.rb +1 -1
  299. data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
  300. data/spec/spec_tests/sdam_spec.rb +1 -1
  301. data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
  302. data/spec/spec_tests/uri_options_spec.rb +4 -4
  303. data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
  304. data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
  305. data/spec/support/certificates/atlas-ocsp.crt +127 -122
  306. data/spec/support/common_shortcuts.rb +2 -3
  307. data/spec/support/matchers.rb +13 -0
  308. data/spec/support/shared/auth_context.rb +16 -0
  309. data/spec/support/shared/session.rb +2 -2
  310. data/spec/support/spec_config.rb +9 -10
  311. data/spec/support/using_hash.rb +31 -0
  312. data/spec/support/utils.rb +1 -1
  313. data.tar.gz.sig +0 -0
  314. metadata +120 -76
  315. metadata.gz.sig +0 -0
  316. data/lib/mongo/collection/view/builder/find_command.rb +0 -173
  317. data/lib/mongo/collection/view/builder/op_query.rb +0 -94
  318. data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
  319. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
  320. data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
  321. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
  322. data/lib/mongo/server/context.rb +0 -72
  323. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
  324. data/spec/runners/unified/using_hash.rb +0 -34
  325. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
  326. data/spec/support/event_subscriber.rb +0 -221
@@ -24,16 +24,6 @@ module Mongo
24
24
  # @since 2.0.0
25
25
  module Readable
26
26
 
27
- # The query modifier constant.
28
- #
29
- # @since 2.2.0
30
- QUERY = '$query'.freeze
31
-
32
- # The modifiers option constant.
33
- #
34
- # @since 2.2.0
35
- MODIFIERS = 'modifiers'.freeze
36
-
37
27
  # Execute an aggregation on the collection view.
38
28
  #
39
29
  # @example Aggregate documents.
@@ -169,13 +159,15 @@ module Mongo
169
159
  selector = ServerSelector.get(read_pref || server_selector)
170
160
  with_session(opts) do |session|
171
161
  read_with_retry(session, selector) do |server|
172
- apply_collation!(cmd, server, opts)
173
162
  Operation::Count.new(
174
- :selector => cmd,
175
- :db_name => database.name,
176
- :options => {:limit => -1},
177
- :read => read_pref,
178
- :session => session,
163
+ selector: cmd,
164
+ db_name: database.name,
165
+ options: {:limit => -1},
166
+ read: read_pref,
167
+ session: session,
168
+ # For some reason collation was historically accepted as a
169
+ # string key. Note that this isn't documented as valid usage.
170
+ collation: opts[:collation] || opts['collation'] || collation,
179
171
  ).execute(server, context: Operation::Context.new(client: client, session: session))
180
172
  end.n.to_i
181
173
  end
@@ -243,8 +235,8 @@ module Mongo
243
235
  read_pref = opts[:read] || read_preference
244
236
  selector = ServerSelector.get(read_pref || server_selector)
245
237
  with_session(opts) do |session|
246
- context = Operation::Context.new(client: client, session: session)
247
238
  read_with_retry(session, selector) do |server|
239
+ context = Operation::Context.new(client: client, session: session)
248
240
  if server.description.server_version_gte?('5.0')
249
241
  pipeline = [
250
242
  {'$collStats' => {'count' => {}}},
@@ -315,14 +307,16 @@ module Mongo
315
307
  selector = ServerSelector.get(read_pref || server_selector)
316
308
  with_session(opts) do |session|
317
309
  read_with_retry(session, selector) do |server|
318
- apply_collation!(cmd, server, opts)
319
- Operation::Distinct.new({
320
- :selector => cmd,
321
- :db_name => database.name,
322
- :options => {:limit => -1},
323
- :read => read_pref,
324
- :session => session,
325
- }).execute(server, context: Operation::Context.new(client: client, session: session))
310
+ Operation::Distinct.new(
311
+ selector: cmd,
312
+ db_name: database.name,
313
+ options: {:limit => -1},
314
+ read: read_pref,
315
+ session: session,
316
+ # For some reason collation was historically accepted as a
317
+ # string key. Note that this isn't documented as valid usage.
318
+ collation: opts[:collation] || opts['collation'] || collation,
319
+ ).execute(server, context: Operation::Context.new(client: client, session: session))
326
320
  end.first['values']
327
321
  end
328
322
  end
@@ -542,7 +536,11 @@ module Mongo
542
536
  configure(:sort, spec)
543
537
  end
544
538
 
545
- # “meta” operators that let you modify the output or behavior of a query.
539
+ # If called without arguments or with a nil argument, returns
540
+ # the legacy (OP_QUERY) server modifiers for the current view.
541
+ # If called with a non-nil argument, which must be a Hash or a
542
+ # subclass, merges the provided modifiers into the current view.
543
+ # Both string and symbol keys are allowed in the input hash.
546
544
  #
547
545
  # @example Set the modifiers document.
548
546
  # view.modifiers(:$orderby => Mongo::Index::ASCENDING)
@@ -553,8 +551,11 @@ module Mongo
553
551
  #
554
552
  # @since 2.1.0
555
553
  def modifiers(doc = nil)
556
- return Builder::Modifiers.map_server_modifiers(options) if doc.nil?
557
- new(options.merge(Builder::Modifiers.map_driver_options(doc)))
554
+ if doc.nil?
555
+ Operation::Find::Builder::Modifiers.map_server_modifiers(options)
556
+ else
557
+ new(options.merge(Operation::Find::Builder::Modifiers.map_driver_options(BSON::Document.new(doc))))
558
+ end
558
559
  end
559
560
 
560
561
  # A cumulative time limit in milliseconds for processing get more operations
@@ -645,34 +646,42 @@ module Mongo
645
646
 
646
647
  def parallel_scan(cursor_count, options = {})
647
648
  if options[:session]
649
+ # The session would be overwritten by the one in +options+ later.
648
650
  session = client.send(:get_session, @options)
649
651
  else
650
652
  session = nil
651
653
  end
652
654
  server = server_selector.select_server(cluster, nil, session)
653
- cmd = Operation::ParallelScan.new({
654
- :coll_name => collection.name,
655
- :db_name => database.name,
656
- :cursor_count => cursor_count,
657
- :read_concern => read_concern,
658
- :session => session,
659
- }.merge!(options))
660
- cmd.execute(server, context: Operation::Context.new(client: client, session: session)).cursor_ids.map do |cursor_id|
661
- result = if server.with_connection { |connection| connection.features }.find_command_enabled?
662
- Operation::GetMore.new({
663
- :selector => {:getMore => BSON::Int64.new(cursor_id),
664
- :collection => collection.name},
665
- :db_name => database.name,
666
- :session => session,
667
- }).execute(server, context: Operation::Context.new(client: client, session: session))
668
- else
669
- Operation::GetMore.new({
670
- :to_return => 0,
671
- :cursor_id => BSON::Int64.new(cursor_id),
672
- :db_name => database.name,
673
- :coll_name => collection.name
674
- }).execute(server, context: Operation::Context.new(client: client, session: session))
675
- end
655
+ spec = {
656
+ coll_name: collection.name,
657
+ db_name: database.name,
658
+ cursor_count: cursor_count,
659
+ read_concern: read_concern,
660
+ session: session,
661
+ }.update(options)
662
+ session = spec[:session]
663
+ op = Operation::ParallelScan.new(spec)
664
+ # Note that the context object shouldn't be reused for subsequent
665
+ # GetMore operations.
666
+ context = Operation::Context.new(client: client, session: session)
667
+ result = op.execute(server, context: context)
668
+ result.cursor_ids.map do |cursor_id|
669
+ spec = {
670
+ cursor_id: cursor_id,
671
+ coll_name: collection.name,
672
+ db_name: database.name,
673
+ session: session,
674
+ batch_size: batch_size,
675
+ to_return: 0,
676
+ # max_time_ms is not being passed here, I assume intentionally?
677
+ }
678
+ op = Operation::GetMore.new(spec)
679
+ context = Operation::Context.new(
680
+ client: client,
681
+ session: session,
682
+ service_id: result.connection_description.service_id,
683
+ )
684
+ result = op.execute(server, context: context)
676
685
  Cursor.new(self, result, server, session: session)
677
686
  end
678
687
  end
@@ -46,33 +46,44 @@ 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.
49
51
  #
50
52
  # @return [ BSON::Document, nil ] The document, if found.
51
53
  #
52
54
  # @since 2.0.0
53
55
  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
56
  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,
57
+ write_concern = if opts[:write_concern]
58
+ WriteConcern.get(opts[:write_concern])
59
+ else
60
+ write_concern_with_session(session)
61
+ end
62
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
63
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
64
+ end
65
+
66
+ QueryCache.clear_namespace(collection.namespace)
67
+
68
+ cmd = {
69
+ findAndModify: collection.name,
70
+ query: filter,
71
+ remove: true,
72
+ fields: projection,
73
+ sort: sort,
74
+ maxTimeMS: max_time_ms,
75
+ bypassDocumentValidation: opts[:bypass_document_validation],
76
+ hint: opts[:hint],
77
+ collation: opts[:collation] || opts['collation'] || collation,
78
+ }.compact
79
+
80
+ write_with_retry(session, write_concern) do |server, txn_num|
81
+ Operation::WriteCommand.new(
82
+ selector: cmd,
83
+ db_name: database.name,
84
+ write_concern: write_concern,
85
+ session: session,
86
+ txn_num: txn_num,
76
87
  ).execute(server, context: Operation::Context.new(client: client, session: session))
77
88
  end
78
89
  end.first['value']
@@ -96,6 +107,8 @@ module Mongo
96
107
  # @option opts [ Hash ] :collation The collation to use.
97
108
  # @option opts [ Hash | String ] :hint The index to use for this operation.
98
109
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
110
+ # @option opts [ Hash ] :write_concern The write concern options.
111
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
99
112
  #
100
113
  # @return [ BSON::Document ] The document.
101
114
  #
@@ -127,37 +140,47 @@ module Mongo
127
140
  # @option opts [ Session ] :session The session to use.
128
141
  # @option opts [ Hash | String ] :hint The index to use for this operation.
129
142
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
143
+ # @option opts [ Hash ] :write_concern The write concern options.
144
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
130
145
  #
131
146
  # @return [ BSON::Document ] The document.
132
147
  #
133
148
  # @since 2.0.0
134
149
  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
150
  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,
151
+ write_concern = if opts[:write_concern]
152
+ WriteConcern.get(opts[:write_concern])
153
+ else
154
+ write_concern_with_session(session)
155
+ end
156
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
157
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
158
+ end
159
+
160
+ QueryCache.clear_namespace(collection.namespace)
161
+
162
+ cmd = {
163
+ findAndModify: collection.name,
164
+ query: filter,
165
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
166
+ update: document,
167
+ fields: projection,
168
+ sort: sort,
169
+ new: !!(opts[:return_document] && opts[:return_document] == :after),
170
+ upsert: opts[:upsert],
171
+ maxTimeMS: max_time_ms,
172
+ bypassDocumentValidation: opts[:bypass_document_validation],
173
+ hint: opts[:hint],
174
+ collation: opts[:collation] || opts['collation'] || collation,
175
+ }.compact
176
+
177
+ write_with_retry(session, write_concern) do |server, txn_num|
178
+ Operation::WriteCommand.new(
179
+ selector: cmd,
180
+ db_name: database.name,
181
+ write_concern: write_concern,
182
+ session: session,
183
+ txn_num: txn_num,
161
184
  ).execute(server, context: Operation::Context.new(client: client, session: session))
162
185
  end
163
186
  end.first['value']
@@ -182,26 +205,33 @@ module Mongo
182
205
  #
183
206
  # @since 2.0.0
184
207
  def delete_many(opts = {})
185
- QueryCache.clear_namespace(collection.namespace)
186
-
187
- delete_doc = { Operation::Q => filter, Operation::LIMIT => 0 }
188
208
  with_session(opts) do |session|
189
209
  write_concern = if opts[:write_concern]
190
210
  WriteConcern.get(opts[:write_concern])
191
211
  else
192
212
  write_concern_with_session(session)
193
213
  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))
214
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
215
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
216
+ end
217
+
218
+ QueryCache.clear_namespace(collection.namespace)
197
219
 
220
+ delete_doc = {
221
+ Operation::Q => filter,
222
+ Operation::LIMIT => 0,
223
+ hint: opts[:hint],
224
+ collation: opts[:collation] || opts['collation'] || collation,
225
+ }.compact
226
+
227
+ nro_write_with_retry(session, write_concern) do |server|
198
228
  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,
229
+ deletes: [ delete_doc ],
230
+ db_name: collection.database.name,
231
+ coll_name: collection.name,
232
+ write_concern: write_concern,
233
+ bypass_document_validation: !!opts[:bypass_document_validation],
234
+ session: session,
205
235
  ).execute(server, context: Operation::Context.new(client: client, session: session))
206
236
  end
207
237
  end
@@ -225,27 +255,34 @@ module Mongo
225
255
  #
226
256
  # @since 2.0.0
227
257
  def delete_one(opts = {})
228
- QueryCache.clear_namespace(collection.namespace)
229
-
230
- delete_doc = { Operation::Q => filter, Operation::LIMIT => 1 }
231
258
  with_session(opts) do |session|
232
259
  write_concern = if opts[:write_concern]
233
260
  WriteConcern.get(opts[:write_concern])
234
261
  else
235
262
  write_concern_with_session(session)
236
263
  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))
264
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
265
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
266
+ end
267
+
268
+ QueryCache.clear_namespace(collection.namespace)
240
269
 
270
+ delete_doc = {
271
+ Operation::Q => filter,
272
+ Operation::LIMIT => 1,
273
+ hint: opts[:hint],
274
+ collation: opts[:collation] || opts['collation'] || collation,
275
+ }.compact
276
+
277
+ write_with_retry(session, write_concern) do |server, txn_num|
241
278
  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,
279
+ deletes: [ delete_doc ],
280
+ db_name: collection.database.name,
281
+ coll_name: collection.name,
282
+ write_concern: write_concern,
283
+ bypass_document_validation: !!opts[:bypass_document_validation],
284
+ session: session,
285
+ txn_num: txn_num,
249
286
  ).execute(server, context: Operation::Context.new(client: client, session: session))
250
287
  end
251
288
  end
@@ -274,34 +311,38 @@ module Mongo
274
311
  #
275
312
  # @since 2.0.0
276
313
  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
314
  with_session(opts) do |session|
286
315
  write_concern = if opts[:write_concern]
287
316
  WriteConcern.get(opts[:write_concern])
288
317
  else
289
318
  write_concern_with_session(session)
290
319
  end
320
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
321
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
322
+ end
291
323
 
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))
324
+ QueryCache.clear_namespace(collection.namespace)
325
+
326
+ update_doc = {
327
+ Operation::Q => filter,
328
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
329
+ Operation::U => replacement,
330
+ hint: opts[:hint],
331
+ collation: opts[:collation] || opts['collation'] || collation,
332
+ }.compact
333
+ if opts[:upsert]
334
+ update_doc['upsert'] = true
335
+ end
296
336
 
337
+ write_with_retry(session, write_concern) do |server, txn_num|
297
338
  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,
339
+ updates: [ update_doc ],
340
+ db_name: collection.database.name,
341
+ coll_name: collection.name,
342
+ write_concern: write_concern,
343
+ bypass_document_validation: !!opts[:bypass_document_validation],
344
+ session: session,
345
+ txn_num: txn_num,
305
346
  ).execute(server, context: Operation::Context.new(client: client, session: session))
306
347
  end
307
348
  end
@@ -332,33 +373,38 @@ module Mongo
332
373
  #
333
374
  # @since 2.0.0
334
375
  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
376
  with_session(opts) do |session|
345
377
  write_concern = if opts[:write_concern]
346
378
  WriteConcern.get(opts[:write_concern])
347
379
  else
348
380
  write_concern_with_session(session)
349
381
  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))
382
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
383
+ raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
384
+ end
385
+
386
+ QueryCache.clear_namespace(collection.namespace)
387
+
388
+ update_doc = {
389
+ Operation::Q => filter,
390
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
391
+ Operation::U => spec,
392
+ Operation::MULTI => true,
393
+ hint: opts[:hint],
394
+ collation: opts[:collation] || opts['collation'] || collation,
395
+ }.compact
396
+ if opts[:upsert]
397
+ update_doc['upsert'] = true
398
+ end
354
399
 
400
+ nro_write_with_retry(session, write_concern) do |server|
355
401
  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,
402
+ updates: [ update_doc ],
403
+ db_name: collection.database.name,
404
+ coll_name: collection.name,
405
+ write_concern: write_concern,
406
+ bypass_document_validation: !!opts[:bypass_document_validation],
407
+ session: session,
362
408
  ).execute(server, context: Operation::Context.new(client: client, session: session))
363
409
  end
364
410
  end
@@ -389,83 +435,40 @@ module Mongo
389
435
  #
390
436
  # @since 2.0.0
391
437
  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
438
  with_session(opts) do |session|
401
439
  write_concern = if opts[:write_concern]
402
440
  WriteConcern.get(opts[:write_concern])
403
441
  else
404
442
  write_concern_with_session(session)
405
443
  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?
444
+ if opts[:hint] && write_concern && !write_concern.acknowledged?
434
445
  raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
435
446
  end
436
447
 
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
448
+ QueryCache.clear_namespace(collection.namespace)
449
+
450
+ update_doc = {
451
+ Operation::Q => filter,
452
+ arrayFilters: opts[:array_filters] || opts['array_filters'],
453
+ Operation::U => spec,
454
+ hint: opts[:hint],
455
+ collation: opts[:collation] || opts['collation'] || collation,
456
+ }.compact
457
+ if opts[:upsert]
458
+ update_doc['upsert'] = true
442
459
  end
443
460
 
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)
461
+ write_with_retry(session, write_concern) do |server, txn_num|
462
+ Operation::Update.new(
463
+ updates: [ update_doc ],
464
+ db_name: collection.database.name,
465
+ coll_name: collection.name,
466
+ write_concern: write_concern,
467
+ bypass_document_validation: !!opts[:bypass_document_validation],
468
+ session: session,
469
+ txn_num: txn_num,
470
+ ).execute(server, context: Operation::Context.new(client: client, session: session))
471
+ end
469
472
  end
470
473
  end
471
474
  end