mongo 2.15.1 → 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 (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
@@ -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'
@@ -38,28 +38,29 @@ module Mongo
38
38
  #
39
39
  # @since 2.0.0
40
40
  MAPPINGS = {
41
- :retryable_write_error_label => 9,
41
+ retryable_write_error_label: 9,
42
+ commit_quorum: 9,
42
43
  # Server versions older than 4.2 do not reliably validate options
43
44
  # provided by the client during findAndModify operations, requiring the
44
45
  # driver to raise client-side errors when those options are provided.
45
- :find_and_modify_option_validation => 8,
46
- :transactions => 7,
47
- :scram_sha_256 => 7,
48
- :array_filters => 6,
49
- :op_msg => 6,
50
- :sessions => 6,
51
- :collation => 5,
52
- :max_staleness => 5,
46
+ find_and_modify_option_validation: 8,
47
+ transactions: 7,
48
+ scram_sha_256: 7,
49
+ array_filters: 6,
50
+ op_msg: 6,
51
+ sessions: 6,
52
+ collation: 5,
53
+ max_staleness: 5,
53
54
  # Server versions older than 3.4 do not reliably validate options
54
55
  # provided by the client during update/delete operations, requiring the
55
56
  # driver to raise client-side errors when those options are provided.
56
- :update_delete_option_validation => 5,
57
- :find_command => 4,
58
- :list_collections => 3,
59
- :list_indexes => 3,
60
- :scram_sha_1 => 3,
61
- :write_command => 2,
62
- :users_info => 2
57
+ update_delete_option_validation: 5,
58
+ find_command: 4,
59
+ list_collections: 3,
60
+ list_indexes: 3,
61
+ scram_sha_1: 3,
62
+ write_command: 2,
63
+ users_info: 2,
63
64
  }.freeze
64
65
 
65
66
  # Error message if the server is too old for this version of the driver.
@@ -0,0 +1,33 @@
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 Description
21
+
22
+ # Represents an assumed description of servers behind load balancers.
23
+ class LoadBalancer
24
+ def initialize(address)
25
+ @address = address
26
+ end
27
+
28
+ # @return [ Address ] address The server's address.
29
+ attr_reader :address
30
+ end
31
+ end
32
+ end
33
+ end
@@ -15,8 +15,6 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require 'mongo/server/description/features'
19
-
20
18
  module Mongo
21
19
  class Server
22
20
 
@@ -201,7 +199,8 @@ module Mongo
201
199
  ].freeze
202
200
 
203
201
  # Instantiate the new server description from the result of the hello
204
- # command.
202
+ # command or fabricate a placeholder description for Unknown and
203
+ # LoadBalancer servers.
205
204
  #
206
205
  # @example Instantiate the new description.
207
206
  # Description.new(address, { 'isWritablePrimary' => true }, 0.5)
@@ -209,17 +208,67 @@ module Mongo
209
208
  # @param [ Address ] address The server address.
210
209
  # @param [ Hash ] config The result of the hello command.
211
210
  # @param [ Float ] average_round_trip_time The moving average time (sec) the hello
212
- # call took to complete.
211
+ # command took to complete.
212
+ # @param [ Float ] average_round_trip_time The moving average time (sec)
213
+ # the ismaster call took to complete.
214
+ # @param [ true | false ] load_balancer Whether the server is treated as
215
+ # a load balancer.
216
+ # @param [ true | false ] force_load_balancer Whether the server is
217
+ # forced to be a load balancer.
213
218
  #
214
- # @since 2.0.0
215
- def initialize(address, config = {}, average_round_trip_time = nil)
219
+ # @api private
220
+ def initialize(address, config = {}, average_round_trip_time: nil,
221
+ load_balancer: false, force_load_balancer: false
222
+ )
216
223
  @address = address
217
224
  @config = config
225
+ @load_balancer = !!load_balancer
226
+ @force_load_balancer = !!force_load_balancer
218
227
  @features = Features.new(wire_versions, me || @address.to_s)
219
228
  @average_round_trip_time = average_round_trip_time
220
229
  @last_update_time = Time.now.freeze
221
230
  @last_update_monotime = Utils.monotonic_time
222
231
 
232
+ if load_balancer
233
+ # When loadBalanced=true URI option is set, the driver will refuse
234
+ # to work if the server it communicates with does not set serviceId
235
+ # in ismaster/hello response.
236
+ #
237
+ # In practice, there are currently no server version that actually
238
+ # sets this field.
239
+ #
240
+ # Therefore, when connect=:load_balanced Ruby option is used instead
241
+ # of the loadBalanced=true URI option, if serviceId is not set in
242
+ # ismaster/hello response, the driver fabricates a serviceId and
243
+ # proceeds to treat a server that does not report itself as being
244
+ # behind a load balancer as a server that is behind a load balancer.
245
+ #
246
+ # 5.0+ servers should provide topologyVersion.processId which
247
+ # is specific to the particular process instance. We can use that
248
+ # field as a proxy for serviceId.
249
+ #
250
+ # If the topologyVersion isn't provided for whatever reason, we
251
+ # fabricate a serviceId locally.
252
+ #
253
+ # In either case, a serviceId provided by an actual server behind
254
+ # a load balancer is supposed to be a BSON::ObjectId. The fabricated
255
+ # service ids are strings, to distinguish them from the real ones.
256
+ # In particular processId is also a BSON::ObjectId, but will be
257
+ # mapped to a string for clarity that this is a fake service id.
258
+ if ok? && !service_id
259
+ unless force_load_balancer
260
+ raise Error::MissingServiceId, "The server at #{address.seed} did not provide a service id in handshake response"
261
+ end
262
+
263
+ fake_service_id = if process_id = topology_version && topology_version['processId']
264
+ "process:#{process_id}"
265
+ else
266
+ "fake:#{rand(2**32-1)+1}"
267
+ end
268
+ @config = @config.merge('serviceId' => fake_service_id)
269
+ end
270
+ end
271
+
223
272
  if Mongo::Lint.enabled?
224
273
  # prepopulate cache instance variables
225
274
  hosts
@@ -237,11 +286,23 @@ module Mongo
237
286
  # @return [ Hash ] The actual result from the hello command.
238
287
  attr_reader :config
239
288
 
289
+ # Returns whether this server is a load balancer.
290
+ #
291
+ # @return [ true | false ] Whether this server is a load balancer.
292
+ def load_balancer?
293
+ @load_balancer
294
+ end
295
+
240
296
  # @return [ Features ] features The features for the server.
241
297
  def features
242
298
  @features
243
299
  end
244
300
 
301
+ # @return [ nil | Object ] The service id, if any.
302
+ def service_id
303
+ config['serviceId']
304
+ end
305
+
245
306
  # @return [ Float ] The moving average time the hello call took to complete.
246
307
  attr_reader :average_round_trip_time
247
308
 
@@ -625,6 +686,7 @@ module Mongo
625
686
  #
626
687
  # @since 2.4.0
627
688
  def server_type
689
+ return :load_balancer if load_balancer?
628
690
  return :arbiter if arbiter?
629
691
  return :ghost if ghost?
630
692
  return :sharded if mongos?
@@ -659,6 +721,7 @@ module Mongo
659
721
  #
660
722
  # @since 2.0.0
661
723
  def unknown?
724
+ return false if load_balancer?
662
725
  config.empty? || config.keys == %w(topologyVersion) || !ok?
663
726
  end
664
727
 
@@ -780,6 +843,11 @@ module Mongo
780
843
  config['connectionId']
781
844
  end
782
845
 
846
+ # @api experimental
847
+ def service_id
848
+ config['serviceId']
849
+ end
850
+
783
851
  # Check equality of two descriptions.
784
852
  #
785
853
  # @example Check description equality.
@@ -825,8 +893,19 @@ module Mongo
825
893
  raise ArgumentError, "Bogus required version #{version}"
826
894
  end
827
895
 
896
+ if load_balancer?
897
+ # If we are talking to a load balancer, there is no monitoring
898
+ # and we don't know what server is behind the load balancer.
899
+ # Assume everything is supported.
900
+ # TODO remove this when RUBY-2220 is implemented.
901
+ return true
902
+ end
903
+
828
904
  required_wv >= min_wire_version && required_wv <= max_wire_version
829
905
  end
830
906
  end
831
907
  end
832
908
  end
909
+
910
+ require 'mongo/server/description/features'
911
+ require 'mongo/server/description/load_balancer'
@@ -194,13 +194,12 @@ module Mongo
194
194
  #
195
195
  # @raise [Mongo::Error] If handshake failed.
196
196
  def handshake!
197
- document = handshake_document(
198
- @app_metadata,
199
- server_api: options[:server_api]
197
+ command = handshake_command(
198
+ handshake_document(
199
+ @app_metadata,
200
+ server_api: options[:server_api]
201
+ )
200
202
  )
201
- # TODO (DR): OP_MSG should be used if api version is declared.
202
- # See https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst#id5
203
- command = Protocol::Query.new(Database::ADMIN, Database::COMMAND, document, :limit => -1)
204
203
  payload = command.serialize.to_s
205
204
  message = dispatch_bytes(payload)
206
205
  result = Operation::Result.new(message)
@@ -215,7 +215,8 @@ module Mongo
215
215
  old_description = server.description
216
216
 
217
217
  new_description = Description.new(server.address, result,
218
- server.round_trip_time_averager.average_round_trip_time)
218
+ average_round_trip_time: server.round_trip_time_averager.average_round_trip_time
219
+ )
219
220
 
220
221
  server.cluster.run_sdam_flow(server.description, new_description, awaited: awaited)
221
222
 
@@ -71,32 +71,41 @@ module Mongo
71
71
  raise Error::InternalDriverError, "Connection description cannot be unknown after successful handshake: #{description.inspect}"
72
72
  end
73
73
 
74
- if speculative_auth_doc && (speculative_auth_result = result['speculativeAuthenticate'])
75
- unless description.features.scram_sha_1_enabled?
76
- raise Error::InvalidServerAuthResponse, "Speculative auth succeeded on a pre-3.0 server"
77
- end
78
- case speculative_auth_user.mechanism
79
- when :mongodb_x509
80
- # Done
81
- # We default auth mechanism to scram256, but if user specified
82
- # scram explicitly we may be able to authenticate speculatively
83
- # with scram.
84
- when :scram, :scram256
85
- authenticate!(
86
- speculative_auth_client_nonce: speculative_auth.conversation.client_nonce,
87
- speculative_auth_mech: speculative_auth_user.mechanism,
88
- speculative_auth_result: speculative_auth_result,
89
- )
90
- else
91
- raise Error::InternalDriverError, "Speculative auth unexpectedly succeeded for mechanism #{speculative_auth_user.mechanism.inspect}"
74
+ begin
75
+ if speculative_auth_doc && (speculative_auth_result = result['speculativeAuthenticate'])
76
+ unless description.features.scram_sha_1_enabled?
77
+ raise Error::InvalidServerAuthResponse, "Speculative auth succeeded on a pre-3.0 server"
78
+ end
79
+ case speculative_auth_user.mechanism
80
+ when :mongodb_x509
81
+ # Done
82
+ # We default auth mechanism to scram256, but if user specified
83
+ # scram explicitly we may be able to authenticate speculatively
84
+ # with scram.
85
+ when :scram, :scram256
86
+ authenticate!(
87
+ speculative_auth_client_nonce: speculative_auth.conversation.client_nonce,
88
+ speculative_auth_mech: speculative_auth_user.mechanism,
89
+ speculative_auth_result: speculative_auth_result,
90
+ )
91
+ else
92
+ raise Error::InternalDriverError, "Speculative auth unexpectedly succeeded for mechanism #{speculative_auth_user.mechanism.inspect}"
93
+ end
94
+ elsif !description.arbiter?
95
+ authenticate!
92
96
  end
93
- elsif !description.arbiter?
94
- authenticate!
97
+ rescue Mongo::Error, Mongo::Error::AuthError => exc
98
+ exc.service_id = service_id
99
+ raise
95
100
  end
96
101
 
97
102
  if description.unknown?
98
103
  raise Error::InternalDriverError, "Connection description cannot be unknown after successful authentication: #{description.inspect}"
99
104
  end
105
+
106
+ if server.load_balancer? && !description.mongos?
107
+ raise Error::BadLoadBalancerTarget, "Load-balanced operation requires being connected a mongos, but the server at #{address.seed} reported itself as #{description.server_type.to_s.gsub('_', ' ')}"
108
+ end
100
109
  end
101
110
 
102
111
  private
@@ -111,16 +120,14 @@ module Mongo
111
120
  raise Error::InternalDriverError, "Cannot handshake because there is no usable socket (for #{address})"
112
121
  end
113
122
 
114
- hello_doc = handshake_document(
115
- app_metadata,
116
- speculative_auth_doc: speculative_auth_doc,
117
- server_api: options[:server_api],
123
+ hello_command = handshake_command(
124
+ handshake_document(
125
+ app_metadata,
126
+ speculative_auth_doc: speculative_auth_doc,
127
+ load_balancer: server.load_balancer?,
128
+ server_api: options[:server_api]
129
+ )
118
130
  )
119
-
120
- # TODO (DR): OP_MSG should be used if api version is declared.
121
- # See https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst#id5
122
- hello_command = Protocol::Query.new(Database::ADMIN, Database::COMMAND, hello_doc, :limit => -1)
123
-
124
131
  doc = nil
125
132
  @server.handle_handshake_failure! do
126
133
  begin
@@ -144,6 +151,10 @@ module Mongo
144
151
  end
145
152
  end
146
153
 
154
+ if @server.force_load_balancer?
155
+ doc['serviceId'] ||= "fake:#{rand(2**32-1)+1}"
156
+ end
157
+
147
158
  post_handshake(doc, @server.round_trip_time_averager.average_round_trip_time)
148
159
 
149
160
  doc
@@ -193,7 +204,7 @@ module Mongo
193
204
  # This is a separate method to keep the nesting level down.
194
205
  #
195
206
  # @return [ Server::Description ] The server description calculated from
196
- # hello response for this particular connection.
207
+ # the handshake response for this particular connection.
197
208
  def post_handshake(response, average_rtt)
198
209
  if response["ok"] == 1
199
210
  # Auth mechanism is entirely dependent on the contents of
@@ -210,7 +221,12 @@ module Mongo
210
221
  @sasl_supported_mechanisms = nil
211
222
  end
212
223
 
213
- @description = Description.new(address, response, average_rtt).tap do |new_description|
224
+ @description = Description.new(
225
+ address, response,
226
+ average_round_trip_time: average_rtt,
227
+ load_balancer: server.load_balancer?,
228
+ force_load_balancer: options[:connect] == :load_balanced,
229
+ ).tap do |new_description|
214
230
  @server.cluster.run_sdam_flow(@server.description, new_description)
215
231
  end
216
232
  end