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
@@ -86,8 +86,12 @@ module Mongo
86
86
  # @param [ Mongo::Server ] server The server the connection is for.
87
87
  # @param [ Hash ] options The connection options.
88
88
  #
89
- # @option options [ Integer ] :generation Connection pool's generation
90
- # for this connection.
89
+ # @option options [ Integer ] :generation The generation of this
90
+ # connection. The generation should only be specified in this option
91
+ # when not in load-balancing mode, and it should be the generation
92
+ # of the connection pool when the connection is created. In
93
+ # load-balancing mode, the generation is set on the connection
94
+ # after the handshake completes.
91
95
  # @option options [ Hash ] :server_api The requested server API version.
92
96
  # This hash can have the following items:
93
97
  # - *:version* -- string
@@ -96,6 +100,10 @@ module Mongo
96
100
  #
97
101
  # @since 2.0.0
98
102
  def initialize(server, options = {})
103
+ if server.load_balancer? && options[:generation]
104
+ raise ArgumentError, "Generation cannot be set when server is a load balancer"
105
+ end
106
+
99
107
  @id = server.next_connection_id
100
108
  @monitoring = server.monitoring
101
109
  @options = options.freeze
@@ -173,6 +181,15 @@ module Mongo
173
181
  # authenticated and be usable.
174
182
  @socket, @description, @compressor = do_connect
175
183
 
184
+ if server.load_balancer?
185
+ if Lint.enabled?
186
+ unless service_id
187
+ raise Error::InternalDriverError, "The connection is to a load balancer and it must have service_id set here, but does not"
188
+ end
189
+ end
190
+ @generation = connection_pool.generation_manager.generation(service_id: service_id)
191
+ end
192
+
176
193
  publish_cmap_event(
177
194
  Monitoring::Event::Cmap::ConnectionReady.new(address, id)
178
195
  )
@@ -314,7 +331,12 @@ module Mongo
314
331
  yield
315
332
  rescue Error::SocketError => e
316
333
  @error = e
317
- @server.unknown!(generation: e.generation, stop_push_monitor: true)
334
+ @server.unknown!(
335
+ generation: e.generation,
336
+ # or description.service_id?
337
+ service_id: e.service_id,
338
+ stop_push_monitor: true,
339
+ )
318
340
  raise
319
341
  rescue Error::SocketTimeoutError => e
320
342
  @error = e
@@ -88,12 +88,20 @@ module Mongo
88
88
  :max_message_size,
89
89
  :mongos?
90
90
 
91
+ # @return [ nil | Object ] The service id, if any.
92
+ def service_id
93
+ description&.service_id
94
+ end
95
+
91
96
  # Connection pool generation from which this connection was created.
92
97
  # May be nil.
93
98
  #
94
99
  # @return [ Integer | nil ] Connection pool generation.
95
100
  def generation
96
- options[:generation]
101
+ # If the connection is to a load balancer, @generation is set
102
+ # after handshake completes. If the connection is to another server
103
+ # type, generation is specified during connection creation.
104
+ @generation || options[:generation]
97
105
  end
98
106
 
99
107
  def app_metadata
@@ -167,6 +175,7 @@ module Mongo
167
175
  socket_object_id: socket.object_id, connection_id: id,
168
176
  connection_generation: generation,
169
177
  server_connection_id: description.server_connection_id,
178
+ service_id: description.service_id,
170
179
  )
171
180
  start = Utils.monotonic_time
172
181
  result = nil
@@ -184,6 +193,7 @@ module Mongo
184
193
  command_failed(nil, address, operation_id, message.payload,
185
194
  e.message, total_duration,
186
195
  started_event: started_event,
196
+ service_id: description.service_id,
187
197
  )
188
198
  raise
189
199
  else
@@ -191,6 +201,7 @@ module Mongo
191
201
  command_completed(result, address, operation_id, message.payload,
192
202
  total_duration,
193
203
  started_event: started_event,
204
+ service_id: description.service_id,
194
205
  )
195
206
  end
196
207
  if result && context.decrypt?
@@ -57,13 +57,15 @@ module Mongo
57
57
  # @param [ Server::AppMetadata ] app_metadata Application metadata
58
58
  # @param [ BSON::Document ] speculative_auth_doc The speculative
59
59
  # authentication document, if any.
60
+ # @param [ true | false ] load_balancer Whether the connection is to
61
+ # a load balancer.
60
62
  # @param server_api [ Hash | nil ] server_api Server API version.
61
63
  #
62
64
  # @return [BSON::Document] Document that should be sent to a server
63
65
  # for handshake purposes.
64
66
  #
65
67
  # @api private
66
- def handshake_document(app_metadata, speculative_auth_doc: nil, server_api: nil)
68
+ def handshake_document(app_metadata, speculative_auth_doc: nil, load_balancer: false, server_api: nil)
67
69
  serv_api = app_metadata.server_api || server_api
68
70
  document = if serv_api
69
71
  HELLO_DOC.merge(Utils.transform_server_api(serv_api))
@@ -74,6 +76,33 @@ module Mongo
74
76
  if speculative_auth_doc
75
77
  doc.update(speculativeAuthenticate: speculative_auth_doc)
76
78
  end
79
+ if load_balancer
80
+ doc.update(loadBalanced: true)
81
+ end
82
+ end
83
+ end
84
+
85
+ # Build a command that should be used for connection handshake.
86
+ #
87
+ # @param [ BSON::Document ] handshake_document Document that should be
88
+ # sent to a server for handshake purpose.
89
+ #
90
+ # @return [ Protocol::Message ] Command that should be sent to a server
91
+ # for handshake purposes.
92
+ #
93
+ # @api private
94
+ def handshake_command(handshake_document)
95
+ if handshake_document['apiVersion']
96
+ Protocol::Msg.new(
97
+ [], {}, handshake_document.merge({'$db' => Database::ADMIN})
98
+ )
99
+ else
100
+ Protocol::Query.new(
101
+ Database::ADMIN,
102
+ Database::COMMAND,
103
+ handshake_document,
104
+ :limit => -1
105
+ )
77
106
  end
78
107
  end
79
108
 
@@ -125,10 +154,18 @@ module Mongo
125
154
  if respond_to?(:id)
126
155
  note << ", connection #{generation}:#{id}"
127
156
  end
157
+ # Non-monitoring connections have service id.
158
+ # Monitoring connections do not.
159
+ if respond_to?(:service_id) && service_id
160
+ note << ", service id #{service_id}"
161
+ end
128
162
  e.add_note(note)
129
163
  if respond_to?(:generation)
130
164
  # Non-monitoring connections
131
165
  e.generation = generation
166
+ if respond_to?(:description)
167
+ e.service_id = service_id
168
+ end
132
169
  end
133
170
  raise e
134
171
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Mongo
19
+ class Server
20
+ class ConnectionPool
21
+
22
+ # @api private
23
+ class GenerationManager
24
+
25
+ def initialize(server:)
26
+ @map = Hash.new { |hash, key| hash[key] = 1 }
27
+ @server = server
28
+ @lock = Mutex.new
29
+ end
30
+
31
+ attr_reader :server
32
+
33
+ def generation(service_id: nil)
34
+ if service_id
35
+ unless server.load_balancer?
36
+ raise ArgumentError, "Generation scoping to services is only available in load-balanced mode, but the server at #{server.address} is not a load balancer"
37
+ end
38
+ else
39
+ if server.load_balancer?
40
+ raise ArgumentError, "The server at #{server.address} is a load balancer and therefore does not have a single global generation"
41
+ end
42
+ end
43
+ @lock.synchronize do
44
+ @map[service_id]
45
+ end
46
+ end
47
+
48
+ def bump(service_id: nil)
49
+ @lock.synchronize do
50
+ if service_id
51
+ @map[service_id] += 1
52
+ else
53
+ # When service id is not supplied, one of two things may be
54
+ # happening;
55
+ #
56
+ # 1. The pool is not to a load balancer, in which case we only
57
+ # need to increment the generation for the nil service_id.
58
+ # 2. The pool is to a load balancer, in which case we need to
59
+ # increment the generation for each service.
60
+ #
61
+ # Incrementing everything in the map accomplishes both tasks.
62
+ @map.each do |k, v|
63
+ @map[k] += 1
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -14,7 +14,6 @@
14
14
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
- require 'mongo/server/connection_pool/populator'
18
17
 
19
18
  module Mongo
20
19
  class Server
@@ -111,7 +110,7 @@ module Mongo
111
110
  @server = server
112
111
  @options = options.freeze
113
112
 
114
- @generation = 1
113
+ @generation_manager = GenerationManager.new(server: server)
115
114
  @closed = false
116
115
 
117
116
  # A connection owned by this pool should be either in the
@@ -189,12 +188,14 @@ module Mongo
189
188
  @max_idle_time ||= options[:max_idle_time]
190
189
  end
191
190
 
191
+ # @api private
192
+ attr_reader :generation_manager
193
+
192
194
  # @return [ Integer ] generation Generation of connections currently
193
195
  # being used by the queue.
194
196
  #
195
- # @since 2.9.0
196
197
  # @api private
197
- attr_reader :generation
198
+ def_delegator :generation_manager, :generation
198
199
 
199
200
  # Size of the connection pool.
200
201
  #
@@ -277,7 +278,7 @@ module Mongo
277
278
  # and remains so for longer than the wait timeout.
278
279
  #
279
280
  # @since 2.9.0
280
- def check_out
281
+ def check_out(service_id: nil)
281
282
  check_invariants
282
283
 
283
284
  publish_cmap_event(
@@ -306,7 +307,12 @@ module Mongo
306
307
  # a connection while this thread is waiting for one.
307
308
  @lock.synchronize do
308
309
  until @available_connections.empty?
309
- connection = @available_connections.pop
310
+ connection = next_available_connection(service_id: service_id)
311
+
312
+ # If service_id is not nil, connection may be nil here
313
+ # even if there are available connections in the pool
314
+ # (they could be to other services).
315
+ break unless connection
310
316
 
311
317
  if connection.pid != pid
312
318
  log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{connection.pid}, new pid #{pid}")
@@ -315,7 +321,7 @@ module Mongo
315
321
  next
316
322
  end
317
323
 
318
- if connection.generation != generation
324
+ if connection.generation != generation(service_id: connection.service_id)
319
325
  # Stale connections should be disconnected in the clear
320
326
  # method, but if any don't, check again here
321
327
  connection.disconnect!(reason: :stale)
@@ -335,12 +341,22 @@ module Mongo
335
341
  throw(:done)
336
342
  end
337
343
 
338
- # Ruby does not allow a thread to lock a mutex which it already
339
- # holds.
340
- if unsynchronized_size < max_size
341
- connection = create_connection
342
- @pending_connections << connection
343
- throw(:done)
344
+ if service_id
345
+ # If we need a connection to a particular service, we can't
346
+ # create one if we don't already have one, but we can wait
347
+ # for an in-progress operation to return such a connection
348
+ # to the pool, or for the populator to create a suitable
349
+ # connection.
350
+ else
351
+ # If we are below pool capacity, create a new connection.
352
+ #
353
+ # Ruby does not allow a thread to lock a mutex which it already
354
+ # holds.
355
+ if unsynchronized_size < max_size
356
+ connection = create_connection
357
+ @pending_connections << connection
358
+ throw(:done)
359
+ end
344
360
  end
345
361
  end
346
362
 
@@ -354,8 +370,14 @@ module Mongo
354
370
  )
355
371
 
356
372
  msg = @lock.synchronize do
373
+ service_id_msg = if service_id
374
+ " for service #{service_id}"
375
+ else
376
+ ''
377
+ end
378
+
357
379
  "Timed out attempting to check out a connection " +
358
- "from pool for #{@server.address} after #{wait_timeout} sec. " +
380
+ "from pool for #{@server.address}#{service_id_msg} after #{wait_timeout} sec. " +
359
381
  "Connections in pool: #{@available_connections.length} available, " +
360
382
  "#{@checked_out_connections.length} checked out, " +
361
383
  "#{@pending_connections.length} pending " +
@@ -449,7 +471,7 @@ module Mongo
449
471
  # Connection was closed - for example, because it experienced
450
472
  # a network error. Nothing else needs to be done here.
451
473
  @populate_semaphore.signal
452
- elsif connection.generation != @generation
474
+ elsif connection.generation != generation(service_id: connection.service_id)
453
475
  connection.disconnect!(reason: :stale)
454
476
  @populate_semaphore.signal
455
477
  else
@@ -473,8 +495,12 @@ module Mongo
473
495
  # @option options [ true | false ] :lazy If true, do not close any of
474
496
  # the idle connections and instead let them be closed during a
475
497
  # subsequent check out operation.
498
+ # @option options [ Object ] :service_id Discard state for the specified
499
+ # service id only.
476
500
  # @option options [ true | false ] :stop_populator Whether to stop
477
501
  # the populator background thread. For internal driver use only.
502
+ # @option options [ Object ] :service_id Clear connections with
503
+ # the specified service id only.
478
504
  #
479
505
  # @return [ true ] true.
480
506
  #
@@ -488,18 +514,38 @@ module Mongo
488
514
  stop_populator
489
515
  end
490
516
 
517
+ service_id = options && options[:service_id]
518
+
491
519
  @lock.synchronize do
492
- @generation += 1
520
+ @generation_manager.bump(service_id: service_id)
493
521
 
494
522
  publish_cmap_event(
495
- Monitoring::Event::Cmap::PoolCleared.new(@server.address)
523
+ Monitoring::Event::Cmap::PoolCleared.new(
524
+ @server.address,
525
+ service_id: service_id,
526
+ )
496
527
  )
497
528
 
498
529
  unless options && options[:lazy]
499
- until @available_connections.empty?
500
- connection = @available_connections.pop
501
- connection.disconnect!(reason: :stale)
502
- @populate_semaphore.signal
530
+ if service_id
531
+ loop do
532
+ conn = @available_connections.detect do |conn|
533
+ conn.service_id == service_id
534
+ end
535
+ if conn
536
+ @available_connections.delete(conn)
537
+ conn.disconnect!(reason: :stale)
538
+ @populate_semaphore.signal
539
+ else
540
+ break
541
+ end
542
+ end
543
+ else
544
+ until @available_connections.empty?
545
+ connection = @available_connections.pop
546
+ connection.disconnect!(reason: :stale)
547
+ @populate_semaphore.signal
548
+ end
503
549
  end
504
550
  end
505
551
  end
@@ -586,10 +632,10 @@ module Mongo
586
632
  # @return [ Object ] The result of the block.
587
633
  #
588
634
  # @since 2.0.0
589
- def with_connection
635
+ def with_connection(service_id: nil)
590
636
  raise_if_closed!
591
637
 
592
- connection = check_out
638
+ connection = check_out(service_id: service_id)
593
639
  yield(connection)
594
640
  ensure
595
641
  if connection
@@ -705,13 +751,33 @@ module Mongo
705
751
 
706
752
  private
707
753
 
754
+ # Returns the next available connection, optionally scoped to the
755
+ # specified service. If no suitable connections are available,
756
+ # returns nil.
757
+ def next_available_connection(service_id: nil)
758
+ if service_id
759
+ conn = @available_connections.detect do |conn|
760
+ conn.service_id == service_id
761
+ end
762
+ if conn
763
+ @available_connections.delete(conn)
764
+ end
765
+ conn
766
+ else
767
+ @available_connections.pop
768
+ end
769
+ end
770
+
708
771
  def create_connection
709
- connection = Connection.new(@server, options.merge(
710
- generation: generation,
772
+ opts = options.merge(
711
773
  connection_pool: self,
712
774
  # Do not pass app metadata - this will be retrieved by the connection
713
775
  # based on the auth needs.
714
- ))
776
+ )
777
+ unless @server.load_balancer?
778
+ opts[:generation] = generation
779
+ end
780
+ connection = Connection.new(@server, opts)
715
781
  end
716
782
 
717
783
  # Create a connection, connect it, and add it to the pool.
@@ -772,7 +838,11 @@ module Mongo
772
838
  raise
773
839
  end
774
840
  rescue Error::SocketError, Error::SocketTimeoutError => exc
775
- @server.unknown!(generation: exc.generation, stop_push_monitor: true)
841
+ @server.unknown!(
842
+ generation: exc.generation,
843
+ service_id: exc.service_id,
844
+ stop_push_monitor: true,
845
+ )
776
846
  raise
777
847
  end
778
848
 
@@ -800,3 +870,6 @@ module Mongo
800
870
  end
801
871
  end
802
872
  end
873
+
874
+ require 'mongo/server/connection_pool/generation_manager'
875
+ require 'mongo/server/connection_pool/populator'