mongo 2.15.0 → 2.16.0.alpha1

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 (328) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -1
  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 +58 -24
  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 +72 -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/push_monitor.rb +6 -0
  102. data/lib/mongo/server.rb +73 -26
  103. data/lib/mongo/server_selector/base.rb +5 -1
  104. data/lib/mongo/session/session_pool.rb +11 -0
  105. data/lib/mongo/session.rb +21 -1
  106. data/lib/mongo/socket/ocsp_verifier.rb +6 -37
  107. data/lib/mongo/uri/options_mapper.rb +1 -0
  108. data/lib/mongo/uri/srv_protocol.rb +6 -8
  109. data/lib/mongo/uri.rb +18 -0
  110. data/lib/mongo/utils.rb +0 -7
  111. data/lib/mongo/version.rb +1 -1
  112. data/mongo.gemspec +1 -1
  113. data/spec/integration/auth_spec.rb +31 -1
  114. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  115. data/spec/integration/bulk_write_spec.rb +1 -1
  116. data/spec/integration/change_stream_spec.rb +3 -3
  117. data/spec/integration/client_construction_spec.rb +54 -0
  118. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  119. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  120. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  121. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  122. data/spec/integration/client_spec.rb +2 -0
  123. data/spec/integration/command_monitoring_spec.rb +1 -1
  124. data/spec/integration/command_spec.rb +1 -1
  125. data/spec/integration/connection_spec.rb +52 -35
  126. data/spec/integration/crud_spec.rb +174 -1
  127. data/spec/integration/cursor_pinning_spec.rb +121 -0
  128. data/spec/integration/cursor_reaping_spec.rb +8 -4
  129. data/spec/integration/fork_reconnect_spec.rb +1 -5
  130. data/spec/integration/get_more_spec.rb +1 -1
  131. data/spec/integration/heartbeat_events_spec.rb +1 -1
  132. data/spec/integration/map_reduce_spec.rb +77 -0
  133. data/spec/integration/query_cache_spec.rb +47 -2
  134. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  135. data/spec/integration/read_concern_spec.rb +1 -1
  136. data/spec/integration/read_preference_spec.rb +1 -1
  137. data/spec/integration/reconnect_spec.rb +30 -12
  138. data/spec/integration/retryable_errors_spec.rb +1 -1
  139. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  140. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  141. data/spec/integration/sdam_error_handling_spec.rb +5 -3
  142. data/spec/integration/sdam_events_spec.rb +35 -19
  143. data/spec/integration/sdam_prose_spec.rb +1 -1
  144. data/spec/integration/server_monitor_spec.rb +1 -0
  145. data/spec/integration/server_selector_spec.rb +22 -5
  146. data/spec/integration/server_spec.rb +2 -0
  147. data/spec/integration/srv_monitoring_spec.rb +1 -1
  148. data/spec/integration/step_down_spec.rb +1 -1
  149. data/spec/integration/transaction_pinning_spec.rb +120 -0
  150. data/spec/integration/versioned_api_examples_spec.rb +45 -0
  151. data/spec/integration/x509_auth_spec.rb +1 -1
  152. data/spec/lite_spec_helper.rb +1 -2
  153. data/spec/mongo/address/unix_spec.rb +1 -0
  154. data/spec/mongo/auth/cr_spec.rb +2 -3
  155. data/spec/mongo/auth/ldap_spec.rb +2 -3
  156. data/spec/mongo/auth/scram_spec.rb +2 -3
  157. data/spec/mongo/auth/user/view_spec.rb +1 -1
  158. data/spec/mongo/auth/x509_spec.rb +2 -3
  159. data/spec/mongo/bulk_write_spec.rb +3 -3
  160. data/spec/mongo/client_construction_spec.rb +259 -28
  161. data/spec/mongo/client_spec.rb +6 -4
  162. data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
  163. data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
  164. data/spec/mongo/cluster_spec.rb +44 -3
  165. data/spec/mongo/collection/view/aggregation_spec.rb +1 -1
  166. data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
  167. data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
  168. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  169. data/spec/mongo/collection_crud_spec.rb +7 -2
  170. data/spec/mongo/collection_ddl_spec.rb +1 -1
  171. data/spec/mongo/collection_spec.rb +1 -1
  172. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
  173. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
  174. data/spec/mongo/cursor_spec.rb +15 -5
  175. data/spec/mongo/database_spec.rb +15 -15
  176. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  177. data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
  178. data/spec/mongo/grid/stream/write_spec.rb +3 -9
  179. data/spec/mongo/grid/stream_spec.rb +1 -1
  180. data/spec/mongo/index/view_spec.rb +2 -2
  181. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  182. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
  183. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
  184. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  185. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  186. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  187. data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
  188. data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
  189. data/spec/mongo/operation/read_preference_op_msg_spec.rb +2 -0
  190. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  191. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  192. data/spec/mongo/query_cache_spec.rb +6 -2
  193. data/spec/mongo/server/connection_common_spec.rb +62 -11
  194. data/spec/mongo/server/connection_pool_spec.rb +73 -7
  195. data/spec/mongo/server/connection_spec.rb +138 -43
  196. data/spec/mongo/server/description_spec.rb +1 -1
  197. data/spec/mongo/server/monitor_spec.rb +4 -3
  198. data/spec/mongo/session/session_pool_spec.rb +42 -10
  199. data/spec/mongo/session_transaction_spec.rb +15 -30
  200. data/spec/mongo/socket/unix_spec.rb +1 -0
  201. data/spec/mongo/uri_option_parsing_spec.rb +38 -5
  202. data/spec/runners/change_streams/test.rb +1 -1
  203. data/spec/runners/cmap.rb +1 -1
  204. data/spec/runners/connection_string.rb +7 -3
  205. data/spec/runners/crud/operation.rb +5 -3
  206. data/spec/runners/crud/requirement.rb +1 -0
  207. data/spec/runners/crud.rb +1 -1
  208. data/spec/runners/sdam.rb +2 -1
  209. data/spec/runners/transactions/test.rb +2 -2
  210. data/spec/runners/unified/assertions.rb +2 -3
  211. data/spec/runners/unified/event_subscriber.rb +2 -2
  212. data/spec/runners/unified/test.rb +3 -0
  213. data/spec/runners/unified.rb +1 -1
  214. data/spec/shared/lib/mrss/constraints.rb +11 -5
  215. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  216. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  217. data/spec/shared/share/Dockerfile.erb +2 -1
  218. data/spec/shared/shlib/server.sh +70 -20
  219. data/spec/spec_tests/change_streams_spec.rb +1 -1
  220. data/spec/spec_tests/cmap_spec.rb +4 -1
  221. data/spec/spec_tests/command_monitoring_spec.rb +2 -2
  222. data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
  223. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  224. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  225. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  226. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  227. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  228. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  229. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  230. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  231. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  232. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  233. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  234. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  235. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  236. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  237. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  238. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  239. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  240. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  241. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
  242. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  243. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
  244. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  245. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
  246. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  247. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
  248. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  249. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
  250. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
  251. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
  252. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
  253. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
  254. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
  255. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
  256. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  257. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  258. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  259. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  260. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  261. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
  262. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
  263. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  264. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  265. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  266. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  267. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  268. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  269. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  270. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  271. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  272. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  273. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  274. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  275. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  276. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  277. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  278. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  279. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  280. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  281. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  282. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  283. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  284. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  285. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  286. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  287. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  288. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  289. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
  290. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
  291. data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
  292. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
  293. data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
  294. data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
  295. data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
  296. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  297. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  298. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  299. data/spec/spec_tests/sdam_integration_spec.rb +1 -1
  300. data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
  301. data/spec/spec_tests/sdam_spec.rb +1 -1
  302. data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
  303. data/spec/spec_tests/uri_options_spec.rb +4 -4
  304. data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
  305. data/spec/stress/push_monitor_close_spec.rb +44 -0
  306. data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
  307. data/spec/support/certificates/atlas-ocsp.crt +127 -122
  308. data/spec/support/common_shortcuts.rb +2 -3
  309. data/spec/support/matchers.rb +13 -0
  310. data/spec/support/shared/auth_context.rb +16 -0
  311. data/spec/support/shared/session.rb +2 -2
  312. data/spec/support/spec_config.rb +9 -10
  313. data/spec/support/using_hash.rb +31 -0
  314. data/spec/support/utils.rb +1 -1
  315. data.tar.gz.sig +2 -4
  316. metadata +1050 -1004
  317. metadata.gz.sig +0 -0
  318. data/lib/mongo/collection/view/builder/find_command.rb +0 -173
  319. data/lib/mongo/collection/view/builder/op_query.rb +0 -94
  320. data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
  321. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
  322. data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
  323. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
  324. data/lib/mongo/server/context.rb +0 -72
  325. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
  326. data/spec/runners/unified/using_hash.rb +0 -34
  327. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
  328. data/spec/support/event_subscriber.rb +0 -221
@@ -38,6 +38,7 @@ end
38
38
 
39
39
  require 'mongo/cluster/topology/base'
40
40
  require 'mongo/cluster/topology/no_replica_set_options'
41
+ require 'mongo/cluster/topology/load_balanced'
41
42
  require 'mongo/cluster/topology/replica_set_no_primary'
42
43
  require 'mongo/cluster/topology/replica_set_with_primary'
43
44
  require 'mongo/cluster/topology/sharded'
@@ -50,10 +51,12 @@ module Mongo
50
51
  # The various topologies for server selection.
51
52
  #
52
53
  # @since 2.0.0
54
+ # @api private
53
55
  OPTIONS = {
56
+ direct: Single,
57
+ load_balanced: LoadBalanced,
54
58
  replica_set: ReplicaSetNoPrimary,
55
59
  sharded: Sharded,
56
- direct: Single,
57
60
  }.freeze
58
61
 
59
62
  # Get the initial cluster topology for the provided options.
@@ -71,26 +74,43 @@ module Mongo
71
74
  # @option options [ Symbol ] :connect Deprecated - use :direct_connection
72
75
  # option instead of this option. The connection method to use. This
73
76
  # forces the cluster to behave in the specified way instead of
74
- # auto-discovering. One of :direct, :replica_set, :sharded
77
+ # auto-discovering. One of :direct, :replica_set, :sharded,
78
+ # :load_balanced. If :connect is set to :load_balanced, the driver
79
+ # will behave as if the server is a load balancer even if it isn't
80
+ # connected to a load balancer.
81
+ # @option options [ true | false ] :load_balanced Whether to expect to
82
+ # connect to a load balancer.
75
83
  # @option options [ Symbol ] :replica_set The name of the replica set to
76
84
  # connect to. Servers not in this replica set will be ignored.
77
85
  #
78
- # @return [ ReplicaSet, Sharded, Single ] The topology.
86
+ # @return [ ReplicaSet, Sharded, Single, LoadBalanced ] The topology.
79
87
  #
80
88
  # @since 2.0.0
81
89
  # @api private
82
90
  def initial(cluster, monitoring, options)
91
+ connect = options[:connect]&.to_sym
83
92
  cls = if options[:direct_connection]
84
- if options[:connect] && options[:connect] && options[:connect].to_sym != :direct
85
- raise ArgumentError, "Conflicting topology options: direct_connection=true and connect=#{options[:connect]}"
93
+ if connect && connect != :direct
94
+ raise ArgumentError, "Conflicting topology options: direct_connection=true and connect=#{connect}"
95
+ end
96
+ if options[:load_balanced]
97
+ raise ArgumentError, "Conflicting topology options: direct_connection=true and load_balanced=true"
86
98
  end
87
99
  Single
88
- elsif options[:direct_connection] == false && options[:connect] && options[:connect].to_sym == :direct
89
- raise ArgumentError, "Conflicting topology options: direct_connection=false and connect=#{options[:connect]}"
90
- elsif options.key?(:connect)
100
+ elsif options[:direct_connection] == false && connect && connect == :direct
101
+ raise ArgumentError, "Conflicting topology options: direct_connection=false and connect=#{connect}"
102
+ elsif connect && connect != :load_balanced
103
+ if options[:load_balanced]
104
+ raise ArgumentError, "Conflicting topology options: connect=#{options[:connect].inspect} and load_balanced=true"
105
+ end
91
106
  OPTIONS.fetch(options[:connect].to_sym)
92
107
  elsif options.key?(:replica_set) || options.key?(:replica_set_name)
108
+ if options[:load_balanced]
109
+ raise ArgumentError, "Conflicting topology options: replica_set/replica_set_name and load_balanced=true"
110
+ end
93
111
  ReplicaSetNoPrimary
112
+ elsif options[:load_balanced] || connect == :load_balanced
113
+ LoadBalanced
94
114
  else
95
115
  Unknown
96
116
  end
data/lib/mongo/cluster.rb CHANGED
@@ -159,6 +159,10 @@ module Mongo
159
159
  @sdam_flow_lock = Mutex.new
160
160
  Session::SessionPool.create(self)
161
161
 
162
+ if seeds.empty? && load_balanced?
163
+ raise ArgumentError, 'Load-balanced clusters with no seeds are prohibited'
164
+ end
165
+
162
166
  # The opening topology is always unknown with no servers.
163
167
  # https://github.com/mongodb/specifications/pull/388
164
168
  opening_topology = Topology::Unknown.new(options, monitoring, self)
@@ -171,7 +175,7 @@ module Mongo
171
175
  @seeds = seeds = seeds.uniq
172
176
  servers = seeds.map do |seed|
173
177
  # Server opening events must be sent after topology change events.
174
- # Therefore separate server addition, done here before topoolgy change
178
+ # Therefore separate server addition, done here before topology change
175
179
  # event is published, from starting to monitor the server which is
176
180
  # done later.
177
181
  add(seed, monitor: false)
@@ -179,11 +183,20 @@ module Mongo
179
183
 
180
184
  if seeds.size >= 1
181
185
  # Recreate the topology to get the current server list into it
182
- @topology = topology.class.new(topology.options, topology.monitoring, self)
183
- publish_sdam_event(
184
- Monitoring::TOPOLOGY_CHANGED,
185
- Monitoring::Event::TopologyChanged.new(opening_topology, @topology)
186
- )
186
+ recreate_topology(topology, opening_topology)
187
+ end
188
+
189
+ if load_balanced?
190
+ # We are required by the specifications to produce certain SDAM events
191
+ # when in load-balanced topology.
192
+ # These events don't make a lot of sense from the standpoint of the
193
+ # driver's SDAM implementation, nor from the standpoint of the
194
+ # driver's load balancer implementation.
195
+ # They are just required boilerplate.
196
+ #
197
+ # Note that this call must be done above the monitoring_io check
198
+ # because that short-circuits the rest of the constructor.
199
+ fabricate_lb_sdam_events_and_set_server_type
187
200
  end
188
201
 
189
202
  if options[:monitoring_io] == false
@@ -203,7 +216,7 @@ module Mongo
203
216
  @connected = true
204
217
 
205
218
  if options[:cleanup] != false
206
- @cursor_reaper = CursorReaper.new
219
+ @cursor_reaper = CursorReaper.new(self)
207
220
  @socket_reaper = SocketReaper.new(self)
208
221
  @periodic_executor = PeriodicExecutor.new([
209
222
  @cursor_reaper, @socket_reaper,
@@ -212,54 +225,56 @@ module Mongo
212
225
  @periodic_executor.run!
213
226
  end
214
227
 
215
- # Need to record start time prior to starting monitoring
216
- start_monotime = Utils.monotonic_time
217
-
218
- servers.each do |server|
219
- server.start_monitoring
220
- end
228
+ unless load_balanced?
229
+ # Need to record start time prior to starting monitoring
230
+ start_monotime = Utils.monotonic_time
221
231
 
222
- if options[:scan] != false
223
- server_selection_timeout = options[:server_selection_timeout] || ServerSelector::SERVER_SELECTION_TIMEOUT
224
- # The server selection timeout can be very short especially in
225
- # tests, when the client waits for a synchronous scan before
226
- # starting server selection. Limiting the scan to server selection time
227
- # then aborts the scan before it can process even local servers.
228
- # Therefore, allow at least 3 seconds for the scan here.
229
- if server_selection_timeout < 3
230
- server_selection_timeout = 3
232
+ servers.each do |server|
233
+ server.start_monitoring
231
234
  end
232
- deadline = start_monotime + server_selection_timeout
233
- # Wait for the first scan of each server to complete, for
234
- # backwards compatibility.
235
- # If any servers are discovered during this SDAM round we are going to
236
- # wait for these servers to also be queried, and so on, up to the
237
- # server selection timeout or the 3 second minimum.
238
- loop do
239
- # Ensure we do not try to read the servers list while SDAM is running
240
- servers = @sdam_flow_lock.synchronize do
241
- servers_list.dup
242
- end
243
- if servers.all? { |server| server.last_scan_monotime && server.last_scan_monotime >= start_monotime }
244
- break
245
- end
246
- if (time_remaining = deadline - Utils.monotonic_time) <= 0
247
- break
235
+
236
+ if options[:scan] != false
237
+ server_selection_timeout = options[:server_selection_timeout] || ServerSelector::SERVER_SELECTION_TIMEOUT
238
+ # The server selection timeout can be very short especially in
239
+ # tests, when the client waits for a synchronous scan before
240
+ # starting server selection. Limiting the scan to server selection time
241
+ # then aborts the scan before it can process even local servers.
242
+ # Therefore, allow at least 3 seconds for the scan here.
243
+ if server_selection_timeout < 3
244
+ server_selection_timeout = 3
248
245
  end
249
- log_debug("Waiting for up to #{'%.2f' % time_remaining} seconds for servers to be scanned: #{summary}")
250
- # Since the semaphore may have been signaled between us checking
251
- # the servers list above and the wait call below, we should not
252
- # wait for the full remaining time - wait for up to 1 second, then
253
- # recheck the state.
254
- begin
255
- server_selection_semaphore.wait([time_remaining, 1].min)
256
- rescue ::Timeout::Error
257
- # nothing
246
+ deadline = start_monotime + server_selection_timeout
247
+ # Wait for the first scan of each server to complete, for
248
+ # backwards compatibility.
249
+ # If any servers are discovered during this SDAM round we are going to
250
+ # wait for these servers to also be queried, and so on, up to the
251
+ # server selection timeout or the 3 second minimum.
252
+ loop do
253
+ # Ensure we do not try to read the servers list while SDAM is running
254
+ servers = @sdam_flow_lock.synchronize do
255
+ servers_list.dup
256
+ end
257
+ if servers.all? { |server| server.last_scan_monotime && server.last_scan_monotime >= start_monotime }
258
+ break
259
+ end
260
+ if (time_remaining = deadline - Utils.monotonic_time) <= 0
261
+ break
262
+ end
263
+ log_debug("Waiting for up to #{'%.2f' % time_remaining} seconds for servers to be scanned: #{summary}")
264
+ # Since the semaphore may have been signaled between us checking
265
+ # the servers list above and the wait call below, we should not
266
+ # wait for the full remaining time - wait for up to 1 second, then
267
+ # recheck the state.
268
+ begin
269
+ server_selection_semaphore.wait([time_remaining, 1].min)
270
+ rescue ::Timeout::Error
271
+ # nothing
272
+ end
258
273
  end
259
274
  end
260
- end
261
275
 
262
- start_stop_srv_monitor
276
+ start_stop_srv_monitor
277
+ end
263
278
  end
264
279
 
265
280
  # Create a cluster for the provided client, for use when we don't want the
@@ -321,6 +336,14 @@ module Mongo
321
336
  def_delegators :topology, :replica_set?, :replica_set_name, :sharded?,
322
337
  :single?, :unknown?
323
338
 
339
+ # Returns whether the cluster is configured to be in the load-balanced
340
+ # topology.
341
+ #
342
+ # @return [ true | false ] Whether the topology is load-balanced.
343
+ def load_balanced?
344
+ topology.is_a?(Topology::LoadBalanced)
345
+ end
346
+
324
347
  [:register_cursor, :schedule_kill_cursor, :unregister_cursor].each do |m|
325
348
  define_method(m) do |*args|
326
349
  if options[:cleanup] != false
@@ -599,9 +622,25 @@ module Mongo
599
622
  # on 4.2+ servers).
600
623
  # @option aptions [ true | false ] :awaited Whether the updated description
601
624
  # was a result of processing an awaited hello.
625
+ # @option options [ Object ] :service_id Change state for the specified
626
+ # service id only.
602
627
  #
603
628
  # @api private
604
629
  def run_sdam_flow(previous_desc, updated_desc, options = {})
630
+ if load_balanced?
631
+ if updated_desc.config.empty?
632
+ unless options[:keep_connection_pool]
633
+ servers_list.each do |server|
634
+ # TODO should service id be taken out of updated_desc?
635
+ # We could also assert that
636
+ # options[:service_id] == updated_desc.service_id
637
+ server.clear_connection_pool(service_id: options[:service_id])
638
+ end
639
+ end
640
+ end
641
+ return
642
+ end
643
+
605
644
  @sdam_flow_lock.synchronize do
606
645
  flow = SdamFlow.new(self, previous_desc, updated_desc,
607
646
  awaited: options[:awaited])
@@ -782,8 +821,15 @@ module Mongo
782
821
  def add(host, add_options=nil)
783
822
  address = Address.new(host, options)
784
823
  if !addresses.include?(address)
785
- server = Server.new(address, self, @monitoring, event_listeners, options.merge(
786
- monitor: false))
824
+ opts = options.merge(monitor: false)
825
+ # Note that in a load-balanced topology, every server must be a
826
+ # load balancer (load_balancer: true is specified in the options)
827
+ # but this option isn't set here because we are required by the
828
+ # specifications to pretent the server started out as an unknown one
829
+ # and publish server description change event into the load balancer
830
+ # one. The actual correct description for this server will be set
831
+ # by the fabricate_lb_sdam_events_and_set_server_type method.
832
+ server = Server.new(address, self, @monitoring, event_listeners, opts)
787
833
  @update_lock.synchronize do
788
834
  # Need to recheck whether server is present in @servers, because
789
835
  # the previous check was not under a lock.
@@ -899,6 +945,10 @@ module Mongo
899
945
  #
900
946
  # @api private
901
947
  def validate_session_support!
948
+ if topology.is_a?(Topology::LoadBalanced)
949
+ return
950
+ end
951
+
902
952
  @state_change_lock.synchronize do
903
953
  @sdam_flow_lock.synchronize do
904
954
  if topology.data_bearing_servers?
@@ -982,6 +1032,41 @@ module Mongo
982
1032
  msg = "The deployment that the driver is connected to does not support sessions: #{reason}"
983
1033
  raise Error::SessionsNotSupported, msg
984
1034
  end
1035
+
1036
+ def fabricate_lb_sdam_events_and_set_server_type
1037
+ # Although there is no monitoring connection in load balanced mode,
1038
+ # we must emit the following series of SDAM events.
1039
+ server = @servers.first
1040
+ # We are guaranteed to have the server here.
1041
+ server.publish_opening_event
1042
+ server_desc = server.description
1043
+ # This is where a load balancer actually gets its correct server
1044
+ # description.
1045
+ server.update_description(
1046
+ Server::Description.new(server.address, {},
1047
+ load_balancer: true,
1048
+ force_load_balancer: options[:connect] == :load_balanced,
1049
+ )
1050
+ )
1051
+ publish_sdam_event(
1052
+ Monitoring::SERVER_DESCRIPTION_CHANGED,
1053
+ Monitoring::Event::ServerDescriptionChanged.new(
1054
+ server.address,
1055
+ topology,
1056
+ server_desc,
1057
+ server.description
1058
+ )
1059
+ )
1060
+ recreate_topology(topology, topology)
1061
+ end
1062
+
1063
+ def recreate_topology(new_topology_template, previous_topology)
1064
+ @topology = topology.class.new(new_topology_template.options, new_topology_template.monitoring, self)
1065
+ publish_sdam_event(
1066
+ Monitoring::TOPOLOGY_CHANGED,
1067
+ Monitoring::Event::TopologyChanged.new(previous_topology, @topology)
1068
+ )
1069
+ end
985
1070
  end
986
1071
  end
987
1072
 
@@ -121,10 +121,12 @@ module Mongo
121
121
  end
122
122
 
123
123
  def valid_server?(server)
124
- description = server.with_connection do |connection|
125
- connection.description
124
+ if secondary_ok?
125
+ true
126
+ else
127
+ description = server.description
128
+ description.standalone? || description.mongos? || description.primary? || description.load_balancer?
126
129
  end
127
- description.standalone? || description.mongos? || description.primary? || secondary_ok?
128
130
  end
129
131
 
130
132
  def secondary_ok?
@@ -136,16 +138,9 @@ module Mongo
136
138
  log_warn("Rerouting the Aggregation operation to the primary server - #{server.summary} is not suitable")
137
139
  server = cluster.next_primary(nil, session)
138
140
  end
139
- validate_collation!(server)
140
141
  initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
141
142
  end
142
143
 
143
- def validate_collation!(server)
144
- if options[:collation] && !server.with_connection { |connection| connection.features }.collation_enabled?
145
- raise Error::UnsupportedCollation.new
146
- end
147
- end
148
-
149
144
  # Skip, sort, limit, projection are specified as pipeline stages
150
145
  # rather than as options.
151
146
  def cache_options
@@ -79,11 +79,12 @@ module Mongo
79
79
  # @since 2.2.0
80
80
  def specification
81
81
  spec = {
82
- selector: aggregation_command,
83
- db_name: database.name,
84
- read: view.read_preference,
85
- session: @options[:session]
86
- }
82
+ selector: aggregation_command,
83
+ db_name: database.name,
84
+ read: view.read_preference,
85
+ session: @options[:session],
86
+ collation: @options[:collation],
87
+ }
87
88
  if write?
88
89
  spec.update(write_concern: write_concern)
89
90
  end
@@ -36,7 +36,7 @@ module Mongo
36
36
  scope: 'scope',
37
37
  verbose: 'verbose',
38
38
  bypass_document_validation: 'bypassDocumentValidation',
39
- collation: 'collation'
39
+ collation: 'collation',
40
40
  ).freeze
41
41
 
42
42
  def_delegators :@view, :collection, :database, :filter, :read, :write_concern
@@ -71,36 +71,6 @@ module Mongo
71
71
  @options = options
72
72
  end
73
73
 
74
- # Get the specification for issuing a find command on the map/reduce
75
- # results.
76
- #
77
- # @example Get the command specification.
78
- # builder.command_specification
79
- #
80
- # @return [ Hash ] The specification.
81
- #
82
- # @since 2.2.0
83
- def command_specification
84
- {
85
- selector: find_command,
86
- db_name: query_database,
87
- read: read,
88
- session: options[:session]
89
- }
90
- end
91
-
92
- # Get the specification for the document query after a map/reduce.
93
- #
94
- # @example Get the query specification.
95
- # builder.query_specification
96
- #
97
- # @return [ Hash ] The specification.
98
- #
99
- # @since 2.2.0
100
- def query_specification
101
- { selector: {}, options: {}, db_name: query_database, coll_name: query_collection }
102
- end
103
-
104
74
  # Get the specification to pass to the map/reduce operation.
105
75
  #
106
76
  # @example Get the specification.
@@ -113,6 +83,8 @@ module Mongo
113
83
  spec = {
114
84
  selector: map_reduce_command,
115
85
  db_name: database.name,
86
+ # Note that selector just above may also have a read preference
87
+ # specified, per the #map_reduce_command method below.
116
88
  read: read,
117
89
  session: options[:session]
118
90
  }
@@ -121,8 +93,6 @@ module Mongo
121
93
 
122
94
  private
123
95
 
124
- OUT_ACTIONS = [ :replace, :merge, :reduce ].freeze
125
-
126
96
  def write?(spec)
127
97
  if out = spec[:selector][:out]
128
98
  out.is_a?(String) ||
@@ -130,37 +100,30 @@ module Mongo
130
100
  end
131
101
  end
132
102
 
133
- def find_command
134
- BSON::Document.new('find' => query_collection, 'filter' => {})
135
- end
136
-
137
103
  def map_reduce_command
138
104
  command = BSON::Document.new(
139
105
  :mapReduce => collection.name,
140
106
  :map => map,
141
107
  :reduce => reduce,
142
108
  :query => filter,
143
- :out => { inline: 1 }
109
+ :out => { inline: 1 },
144
110
  )
111
+ # Shouldn't this use self.read ?
145
112
  if collection.read_concern
146
113
  command[:readConcern] = Options::Mapper.transform_values_to_strings(
147
114
  collection.read_concern)
148
115
  end
149
- command.merge!(view_options)
116
+ command.update(view_options)
117
+ command.update(Utils.slice_hash(options, :collation))
118
+ # Read preference isn't simply passed in the command payload
119
+ # (it may need to be converted to wire protocol flags)
120
+ # so remove it here and hopefully it's handled elsewhere.
121
+ # If not, RUBY-2706.
122
+ command.delete(:read)
150
123
  command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
151
124
  command
152
125
  end
153
126
 
154
- def query_database
155
- options[:out].respond_to?(:keys) && options[:out][:db] ? options[:out][:db] : database.name
156
- end
157
-
158
- def query_collection
159
- if options[:out].respond_to?(:keys)
160
- options[:out][OUT_ACTIONS.find { |action| options[:out][action] }]
161
- end || options[:out]
162
- end
163
-
164
127
  def view_options
165
128
  @view_options ||= (opts = view.options.dup
166
129
  opts.delete(:session)