mongo 2.15.0 → 2.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (393) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/lib/mongo/auth/aws/request.rb +0 -1
  5. data/lib/mongo/bulk_write.rb +2 -2
  6. data/lib/mongo/client.rb +49 -5
  7. data/lib/mongo/cluster/periodic_executor.rb +4 -3
  8. data/lib/mongo/cluster/reapers/cursor_reaper.rb +76 -43
  9. data/lib/mongo/cluster/sdam_flow.rb +9 -3
  10. data/lib/mongo/cluster/topology/base.rb +13 -9
  11. data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
  12. data/lib/mongo/cluster/topology.rb +28 -8
  13. data/lib/mongo/cluster.rb +136 -51
  14. data/lib/mongo/collection/view/aggregation.rb +63 -23
  15. data/lib/mongo/collection/view/builder/aggregation.rb +16 -17
  16. data/lib/mongo/collection/view/builder/map_reduce.rb +12 -49
  17. data/lib/mongo/collection/view/builder.rb +0 -4
  18. data/lib/mongo/collection/view/change_stream.rb +7 -3
  19. data/lib/mongo/collection/view/iterable.rb +60 -27
  20. data/lib/mongo/collection/view/map_reduce.rb +41 -15
  21. data/lib/mongo/collection/view/readable.rb +84 -52
  22. data/lib/mongo/collection/view/writable.rb +201 -175
  23. data/lib/mongo/collection/view.rb +15 -21
  24. data/lib/mongo/collection.rb +34 -14
  25. data/lib/mongo/cursor/kill_spec.rb +38 -0
  26. data/lib/mongo/cursor.rb +72 -31
  27. data/lib/mongo/database/view.rb +5 -3
  28. data/lib/mongo/database.rb +6 -6
  29. data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
  30. data/lib/mongo/error/missing_service_id.rb +26 -0
  31. data/lib/mongo/error/no_service_connection_available.rb +49 -0
  32. data/lib/mongo/error/notable.rb +7 -0
  33. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
  34. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
  35. data/lib/mongo/error.rb +5 -0
  36. data/lib/mongo/grid/fs_bucket.rb +21 -2
  37. data/lib/mongo/id.rb +7 -5
  38. data/lib/mongo/index/view.rb +22 -41
  39. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +7 -4
  40. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  41. data/lib/mongo/monitoring/event/command_started.rb +2 -0
  42. data/lib/mongo/monitoring/publishable.rb +2 -2
  43. data/lib/mongo/operation/aggregate/command.rb +8 -0
  44. data/lib/mongo/operation/context.rb +19 -1
  45. data/lib/mongo/operation/count/command.rb +6 -0
  46. data/lib/mongo/operation/count/op_msg.rb +6 -0
  47. data/lib/mongo/operation/create/command.rb +7 -1
  48. data/lib/mongo/operation/create/op_msg.rb +7 -0
  49. data/lib/mongo/operation/create_index/command.rb +17 -1
  50. data/lib/mongo/operation/create_index/op_msg.rb +17 -4
  51. data/lib/mongo/operation/delete/command.rb +6 -3
  52. data/lib/mongo/operation/delete/legacy.rb +9 -2
  53. data/lib/mongo/operation/delete/op_msg.rb +9 -1
  54. data/lib/mongo/operation/distinct/command.rb +6 -0
  55. data/lib/mongo/operation/distinct/op_msg.rb +7 -0
  56. data/lib/mongo/operation/explain/command.rb +13 -1
  57. data/lib/mongo/operation/explain/legacy.rb +12 -5
  58. data/lib/mongo/operation/explain/op_msg.rb +9 -1
  59. data/lib/mongo/operation/find/builder/command.rb +111 -0
  60. data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +10 -14
  61. data/lib/mongo/operation/find/builder/legacy.rb +123 -0
  62. data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +31 -25
  63. data/lib/mongo/{cursor → operation/find}/builder.rb +4 -4
  64. data/lib/mongo/operation/find/command.rb +9 -0
  65. data/lib/mongo/operation/find/legacy.rb +10 -1
  66. data/lib/mongo/operation/find/op_msg.rb +12 -0
  67. data/lib/mongo/operation/find.rb +1 -0
  68. data/lib/mongo/operation/get_more/command.rb +1 -0
  69. data/lib/mongo/operation/get_more/command_builder.rb +38 -0
  70. data/lib/mongo/operation/get_more/op_msg.rb +1 -0
  71. data/lib/mongo/operation/get_more.rb +1 -0
  72. data/lib/mongo/operation/kill_cursors/command.rb +8 -0
  73. data/lib/mongo/operation/kill_cursors/command_builder.rb +35 -0
  74. data/lib/mongo/operation/kill_cursors/legacy.rb +2 -1
  75. data/lib/mongo/operation/kill_cursors/op_msg.rb +10 -0
  76. data/lib/mongo/operation/kill_cursors.rb +1 -0
  77. data/lib/mongo/operation/map_reduce/command.rb +8 -0
  78. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  79. data/lib/mongo/operation/result.rb +6 -0
  80. data/lib/mongo/operation/shared/executable.rb +19 -1
  81. data/lib/mongo/operation/shared/polymorphic_operation.rb +1 -1
  82. data/lib/mongo/operation/shared/read_preference_supported.rb +3 -1
  83. data/lib/mongo/operation/shared/response_handling.rb +1 -0
  84. data/lib/mongo/operation/shared/sessions_supported.rb +28 -12
  85. data/lib/mongo/operation/shared/specifiable.rb +11 -29
  86. data/lib/mongo/operation/shared/validatable.rb +87 -0
  87. data/lib/mongo/operation/shared/write.rb +1 -1
  88. data/lib/mongo/operation/update/command.rb +6 -3
  89. data/lib/mongo/operation/update/legacy.rb +19 -11
  90. data/lib/mongo/operation/update/op_msg.rb +8 -4
  91. data/lib/mongo/operation/write_command/command.rb +51 -0
  92. data/lib/mongo/operation/write_command/op_msg.rb +43 -0
  93. data/lib/mongo/operation/write_command.rb +32 -0
  94. data/lib/mongo/operation.rb +10 -0
  95. data/lib/mongo/protocol/query.rb +35 -18
  96. data/lib/mongo/server/connection.rb +25 -3
  97. data/lib/mongo/server/connection_base.rb +12 -1
  98. data/lib/mongo/server/connection_common.rb +38 -1
  99. data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
  100. data/lib/mongo/server/connection_pool.rb +100 -27
  101. data/lib/mongo/server/description/features.rb +20 -17
  102. data/lib/mongo/server/description/load_balancer.rb +33 -0
  103. data/lib/mongo/server/description.rb +85 -6
  104. data/lib/mongo/server/monitor/connection.rb +5 -6
  105. data/lib/mongo/server/monitor.rb +2 -1
  106. data/lib/mongo/server/pending_connection.rb +47 -31
  107. data/lib/mongo/server/push_monitor.rb +10 -1
  108. data/lib/mongo/server.rb +73 -26
  109. data/lib/mongo/server_selector/base.rb +31 -5
  110. data/lib/mongo/session/session_pool.rb +11 -0
  111. data/lib/mongo/session.rb +40 -1
  112. data/lib/mongo/socket/ocsp_cache.rb +2 -3
  113. data/lib/mongo/socket/ocsp_verifier.rb +6 -37
  114. data/lib/mongo/socket.rb +1 -5
  115. data/lib/mongo/uri/options_mapper.rb +1 -0
  116. data/lib/mongo/uri/srv_protocol.rb +6 -8
  117. data/lib/mongo/uri.rb +18 -0
  118. data/lib/mongo/utils.rb +0 -13
  119. data/lib/mongo/version.rb +1 -1
  120. data/mongo.gemspec +1 -1
  121. data/spec/integration/auth_spec.rb +31 -1
  122. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  123. data/spec/integration/bulk_write_spec.rb +1 -1
  124. data/spec/integration/change_stream_spec.rb +3 -3
  125. data/spec/integration/client_construction_spec.rb +54 -0
  126. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  127. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  128. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  129. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  130. data/spec/integration/client_spec.rb +2 -0
  131. data/spec/integration/command_monitoring_spec.rb +1 -1
  132. data/spec/integration/command_spec.rb +1 -1
  133. data/spec/integration/connection_spec.rb +52 -35
  134. data/spec/integration/crud_spec.rb +174 -1
  135. data/spec/integration/cursor_pinning_spec.rb +121 -0
  136. data/spec/integration/cursor_reaping_spec.rb +8 -4
  137. data/spec/integration/fork_reconnect_spec.rb +1 -5
  138. data/spec/integration/get_more_spec.rb +1 -1
  139. data/spec/integration/heartbeat_events_spec.rb +1 -1
  140. data/spec/integration/map_reduce_spec.rb +77 -0
  141. data/spec/integration/query_cache_spec.rb +47 -2
  142. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  143. data/spec/integration/read_concern_spec.rb +1 -1
  144. data/spec/integration/read_preference_spec.rb +17 -13
  145. data/spec/integration/reconnect_spec.rb +30 -12
  146. data/spec/integration/retryable_errors_spec.rb +1 -1
  147. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  148. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  149. data/spec/integration/sdam_error_handling_spec.rb +5 -3
  150. data/spec/integration/sdam_events_spec.rb +35 -19
  151. data/spec/integration/sdam_prose_spec.rb +1 -1
  152. data/spec/integration/server_monitor_spec.rb +1 -0
  153. data/spec/integration/server_selector_spec.rb +22 -5
  154. data/spec/integration/server_spec.rb +2 -0
  155. data/spec/integration/srv_monitoring_spec.rb +1 -1
  156. data/spec/integration/step_down_spec.rb +1 -1
  157. data/spec/integration/transaction_pinning_spec.rb +120 -0
  158. data/spec/integration/versioned_api_examples_spec.rb +45 -0
  159. data/spec/integration/x509_auth_spec.rb +1 -1
  160. data/spec/lite_spec_helper.rb +1 -2
  161. data/spec/mongo/address/unix_spec.rb +1 -0
  162. data/spec/mongo/auth/cr_spec.rb +2 -3
  163. data/spec/mongo/auth/ldap_spec.rb +2 -3
  164. data/spec/mongo/auth/scram_spec.rb +2 -3
  165. data/spec/mongo/auth/user/view_spec.rb +1 -1
  166. data/spec/mongo/auth/x509_spec.rb +2 -3
  167. data/spec/mongo/bulk_write_spec.rb +3 -3
  168. data/spec/mongo/client_construction_spec.rb +259 -28
  169. data/spec/mongo/client_spec.rb +6 -4
  170. data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
  171. data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
  172. data/spec/mongo/cluster_spec.rb +44 -3
  173. data/spec/mongo/collection/view/aggregation_spec.rb +72 -96
  174. data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
  175. data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
  176. data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
  177. data/spec/mongo/collection/view/map_reduce_spec.rb +15 -2
  178. data/spec/mongo/collection_crud_spec.rb +7 -2
  179. data/spec/mongo/collection_ddl_spec.rb +1 -1
  180. data/spec/mongo/collection_spec.rb +1 -1
  181. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
  182. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
  183. data/spec/mongo/cursor_spec.rb +15 -5
  184. data/spec/mongo/database_spec.rb +15 -15
  185. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  186. data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
  187. data/spec/mongo/grid/stream/write_spec.rb +3 -9
  188. data/spec/mongo/grid/stream_spec.rb +1 -1
  189. data/spec/mongo/index/view_spec.rb +2 -2
  190. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  191. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
  192. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
  193. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  194. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  195. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  196. data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
  197. data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
  198. data/spec/mongo/operation/read_preference_op_msg_spec.rb +26 -1
  199. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  200. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  201. data/spec/mongo/query_cache_spec.rb +6 -2
  202. data/spec/mongo/server/connection_common_spec.rb +62 -11
  203. data/spec/mongo/server/connection_pool_spec.rb +73 -7
  204. data/spec/mongo/server/connection_spec.rb +138 -43
  205. data/spec/mongo/server/description_spec.rb +1 -1
  206. data/spec/mongo/server/monitor/connection_spec.rb +22 -0
  207. data/spec/mongo/server/monitor_spec.rb +4 -3
  208. data/spec/mongo/server/push_monitor_spec.rb +101 -0
  209. data/spec/mongo/server_selector_spec.rb +136 -15
  210. data/spec/mongo/session/session_pool_spec.rb +42 -10
  211. data/spec/mongo/session_transaction_spec.rb +15 -30
  212. data/spec/mongo/socket/ssl_spec.rb +26 -58
  213. data/spec/mongo/socket/unix_spec.rb +1 -0
  214. data/spec/mongo/uri_option_parsing_spec.rb +38 -5
  215. data/spec/mongo/utils_spec.rb +0 -14
  216. data/spec/runners/change_streams/test.rb +1 -1
  217. data/spec/runners/cmap.rb +1 -1
  218. data/spec/runners/connection_string.rb +7 -3
  219. data/spec/runners/crud/operation.rb +5 -3
  220. data/spec/runners/crud/requirement.rb +1 -0
  221. data/spec/runners/crud/verifier.rb +1 -2
  222. data/spec/runners/crud.rb +1 -1
  223. data/spec/runners/sdam.rb +2 -1
  224. data/spec/runners/transactions/test.rb +2 -2
  225. data/spec/runners/unified/assertions.rb +5 -4
  226. data/spec/runners/unified/crud_operations.rb +77 -23
  227. data/spec/runners/unified/ddl_operations.rb +29 -1
  228. data/spec/runners/unified/entity_map.rb +3 -3
  229. data/spec/runners/unified/event_subscriber.rb +2 -2
  230. data/spec/runners/unified/support_operations.rb +16 -3
  231. data/spec/runners/unified/test.rb +18 -3
  232. data/spec/runners/unified.rb +1 -1
  233. data/spec/shared/lib/mrss/cluster_config.rb +6 -1
  234. data/spec/shared/lib/mrss/constraints.rb +11 -5
  235. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  236. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  237. data/spec/shared/share/Dockerfile.erb +5 -4
  238. data/spec/shared/shlib/server.sh +70 -20
  239. data/spec/spec_tests/change_streams_spec.rb +1 -1
  240. data/spec/spec_tests/cmap_spec.rb +4 -1
  241. data/spec/spec_tests/command_monitoring_spec.rb +2 -2
  242. data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
  243. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  244. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  245. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  246. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  247. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  248. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  249. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  250. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  251. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  252. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  253. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  254. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  255. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  256. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  257. data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
  258. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
  259. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
  260. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
  261. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
  262. data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
  263. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
  264. data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
  265. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
  266. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
  267. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
  268. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  269. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  270. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  271. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  272. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
  273. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  274. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  275. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  276. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
  277. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
  278. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
  279. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
  280. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
  281. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
  282. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
  283. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
  284. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
  285. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  288. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  289. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  290. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
  291. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  292. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
  293. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
  294. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  295. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
  296. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  297. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
  298. data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
  299. data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
  300. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
  301. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
  302. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  303. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
  304. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  305. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
  306. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  307. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
  308. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  309. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
  310. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
  311. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
  312. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
  313. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
  314. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
  315. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
  316. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  317. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  318. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  319. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  320. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  321. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
  322. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
  323. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  324. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  325. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  326. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  327. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  328. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  329. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  330. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  331. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  332. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  333. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  334. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  335. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  336. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  337. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  338. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  339. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  340. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  341. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  342. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  343. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  344. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  345. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  346. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  347. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  348. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  349. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
  350. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
  351. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
  352. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
  353. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
  354. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
  355. data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
  356. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
  357. data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
  358. data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
  359. data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
  360. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  361. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  362. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  363. data/spec/spec_tests/sdam_integration_spec.rb +1 -1
  364. data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
  365. data/spec/spec_tests/sdam_spec.rb +1 -1
  366. data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
  367. data/spec/spec_tests/sessions_unified_spec.rb +13 -0
  368. data/spec/spec_tests/uri_options_spec.rb +4 -4
  369. data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
  370. data/spec/stress/push_monitor_close_spec.rb +44 -0
  371. data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
  372. data/spec/support/certificates/atlas-ocsp.crt +127 -122
  373. data/spec/support/common_shortcuts.rb +2 -3
  374. data/spec/support/matchers.rb +13 -0
  375. data/spec/support/shared/auth_context.rb +16 -0
  376. data/spec/support/shared/session.rb +2 -2
  377. data/spec/support/spec_config.rb +10 -11
  378. data/spec/support/using_hash.rb +31 -0
  379. data/spec/support/utils.rb +1 -1
  380. data.tar.gz.sig +3 -4
  381. metadata +1111 -1029
  382. metadata.gz.sig +2 -3
  383. data/lib/mongo/collection/view/builder/find_command.rb +0 -173
  384. data/lib/mongo/collection/view/builder/op_query.rb +0 -94
  385. data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
  386. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
  387. data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
  388. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
  389. data/lib/mongo/server/context.rb +0 -72
  390. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
  391. data/spec/runners/unified/using_hash.rb +0 -34
  392. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
  393. data/spec/support/event_subscriber.rb +0 -221
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c6cb18a281d0d5f22242702b2d20547693ce0bb42abcc059b1c9d20e3b5f789
4
- data.tar.gz: 440be33d07fa020f578f6b296a8477ac55dc86cc48cc6521523bbb70bc779f04
3
+ metadata.gz: a7fed7eef29657f665e0b2cbecaab0e60626e76aad58087ff5fd8d051d237002
4
+ data.tar.gz: 77e80dd97d3d60c6836b563233f23d1f505344905d87ff8afedbe31fa45b216a
5
5
  SHA512:
6
- metadata.gz: b451d9af1c891835bedb2f96dbc9a1f21e49548ddb3738f737d22bfc4533c2cdf8c33528c40d6847c4d9926c2cabc312a25b19f153a619f9d251e6750fceaeb6
7
- data.tar.gz: 9cc4befbd2db7323f946f4bbc67b9ee0977ea03f9bfdc627333ceca13c93781aff987e2dc7c3f0cbaa4621f99308ace626913c64f896f3cb507ee8ae6f4f9e93
6
+ metadata.gz: 4a898c56e637b3c0597126cc207d9c70ae9f0b3533294fab7ba92f8882be72a5df44ead386e055433966b40ad7f34ef3d0a5a82ae1c9b3088d4fb2d428673ee8
7
+ data.tar.gz: abec048d264aee514a33c660f0ac151f169f6b764d7e85c91f626a1ecb30e2b27c9ddcf3aa404c0f3e3cc27eb8f00dfe0e223a69096755556cb4942c5be9ce3f
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -5,7 +5,7 @@ MongoDB Ruby Driver
5
5
 
6
6
  The officially supported Ruby driver for [MongoDB](https://www.mongodb.org/).
7
7
 
8
- The Ruby driver supports Ruby 2.3-3.0 and JRuby 9.2.
8
+ The Ruby driver supports Ruby 2.5-3.0 and JRuby 9.2.
9
9
 
10
10
 
11
11
  Documentation
@@ -153,7 +153,6 @@ module Mongo
153
153
  'x-mongodb-gs2-cb-flag' => 'n',
154
154
  'x-mongodb-server-nonce' => Base64.encode64(server_nonce).gsub("\n", ''),
155
155
  }
156
- # Hash#compact is available as of Ruby 2.4
157
156
  if session_token
158
157
  headers['x-amz-security-token'] = session_token
159
158
  end
@@ -66,7 +66,7 @@ module Mongo
66
66
  if single_statement?(operation)
67
67
  write_concern = write_concern(session)
68
68
  write_with_retry(session, write_concern) do |server, txn_num|
69
- server.with_connection do |connection|
69
+ server.with_connection(service_id: context.service_id) do |connection|
70
70
  execute_operation(
71
71
  operation.keys.first,
72
72
  operation.values.flatten,
@@ -80,7 +80,7 @@ module Mongo
80
80
  end
81
81
  else
82
82
  nro_write_with_retry(session, write_concern) do |server|
83
- server.with_connection do |connection|
83
+ server.with_connection(service_id: context.service_id) do |connection|
84
84
  execute_operation(
85
85
  operation.keys.first,
86
86
  operation.values.flatten,
data/lib/mongo/client.rb CHANGED
@@ -67,6 +67,7 @@ module Mongo
67
67
  :database,
68
68
  :heartbeat_frequency,
69
69
  :id_generator,
70
+ :load_balanced,
70
71
  :local_threshold,
71
72
  :logger,
72
73
  :log_prefix,
@@ -243,7 +244,10 @@ module Mongo
243
244
  # @option options [ Symbol ] :connect Deprecated - use :direct_connection
244
245
  # option instead of this option. The connection method to use. This
245
246
  # forces the cluster to behave in the specified way instead of
246
- # auto-discovering. One of :direct, :replica_set, :sharded
247
+ # auto-discovering. One of :direct, :replica_set, :sharded,
248
+ # :load_balanced. If :connect is set to :load_balanced, the driver
249
+ # will behave as if the server is a load balancer even if it isn't
250
+ # connected to a load balancer.
247
251
  # @option options [ Float ] :connect_timeout The timeout, in seconds, to
248
252
  # attempt a connection.
249
253
  # @option options [ String ] :database The database to connect to.
@@ -251,6 +255,8 @@ module Mongo
251
255
  # for the server monitor to refresh its description via hello.
252
256
  # @option options [ Object ] :id_generator A custom object to generate ids
253
257
  # for documents. Must respond to #generate.
258
+ # @option options [ true | false ] :load_balanced Whether to expect to
259
+ # connect to a load balancer.
254
260
  # @option options [ Integer ] :local_threshold The local threshold boundary
255
261
  # in seconds for selecting a near server for an operation.
256
262
  # @option options [ Logger ] :logger A custom logger to use.
@@ -881,6 +887,7 @@ module Mongo
881
887
  #
882
888
  # See https://docs.mongodb.com/manual/reference/command/listDatabases/
883
889
  # for more information and usage.
890
+ # @option opts [ Session ] :session The session to use.
884
891
  #
885
892
  # @return [ Array<String> ] The names of the databases.
886
893
  #
@@ -904,6 +911,7 @@ module Mongo
904
911
  #
905
912
  # See https://docs.mongodb.com/manual/reference/command/listDatabases/
906
913
  # for more information and usage.
914
+ # @option opts [ Session ] :session The session to use.
907
915
  #
908
916
  # @return [ Array<Hash> ] The info for each database.
909
917
  #
@@ -924,6 +932,8 @@ module Mongo
924
932
  # @param [ Hash ] filter The filter criteria for getting a list of databases.
925
933
  # @param [ Hash ] opts The command options.
926
934
  #
935
+ # @option opts [ Session ] :session The session to use.
936
+ #
927
937
  # @return [ Array<Mongo::Database> ] The list of database objects.
928
938
  #
929
939
  # @since 2.5.0
@@ -1234,9 +1244,15 @@ module Mongo
1234
1244
  raise ArgumentError, "If :write and :write_concern are both given, they must be identical: #{options.inspect}"
1235
1245
  end
1236
1246
 
1247
+ connect = options[:connect]&.to_sym
1248
+
1249
+ if connect && !%i(direct replica_set sharded load_balanced).include?(connect)
1250
+ raise ArgumentError, "Invalid :connect option value: #{connect}"
1251
+ end
1252
+
1237
1253
  if options[:direct_connection]
1238
- if options[:connect] && options[:connect].to_sym != :direct
1239
- raise ArgumentError, "Conflicting client options: direct_connection=true and connect=#{options[:connect]}"
1254
+ if connect && connect != :direct
1255
+ raise ArgumentError, "Conflicting client options: direct_connection=true and connect=#{connect}"
1240
1256
  end
1241
1257
  # When a new client is created, we get the list of seed addresses
1242
1258
  if addresses && addresses.length > 1
@@ -1248,8 +1264,36 @@ module Mongo
1248
1264
  end
1249
1265
  end
1250
1266
 
1251
- if options[:direct_connection] == false && options[:connect] && options[:connect].to_sym == :direct
1252
- raise ArgumentError, "Conflicting client options: direct_connection=false and connect=#{options[:connect]}"
1267
+ if options[:load_balanced]
1268
+ if addresses && addresses.length > 1
1269
+ raise ArgumentError, "load_balanced=true cannot be used with multiple seeds"
1270
+ end
1271
+
1272
+ if options[:direct_connection]
1273
+ raise ArgumentError, "direct_connection=true cannot be used with load_balanced=true"
1274
+ end
1275
+
1276
+ if connect && connect != :load_balanced
1277
+ raise ArgumentError, "connect=#{connect} cannot be used with load_balanced=true"
1278
+ end
1279
+
1280
+ if options[:replica_set]
1281
+ raise ArgumentError, "load_balanced=true cannot be used with replica_set option"
1282
+ end
1283
+ end
1284
+
1285
+ if connect == :load_balanced
1286
+ if addresses && addresses.length > 1
1287
+ raise ArgumentError, "connect=load_balanced cannot be used with multiple seeds"
1288
+ end
1289
+
1290
+ if options[:replica_set]
1291
+ raise ArgumentError, "connect=load_balanced cannot be used with replica_set option"
1292
+ end
1293
+ end
1294
+
1295
+ if options[:direct_connection] == false && connect && connect == :direct
1296
+ raise ArgumentError, "Conflicting client options: direct_connection=false and connect=#{connect}"
1253
1297
  end
1254
1298
 
1255
1299
  %i(connect_timeout socket_timeout).each do |key|
@@ -36,14 +36,15 @@ module Mongo
36
36
  #
37
37
  # @example Create a PeriodicExecutor.
38
38
  # Mongo::Cluster::PeriodicExecutor.new([reaper, reaper2])
39
+ #
40
+ # @param [ Array<Object> ] executors The executors. Each must respond
41
+ # to #execute and #flush.
39
42
  # @param [ Hash ] options The options.
40
43
  #
41
44
  # @option options [ Logger ] :logger A custom logger to use.
42
45
  #
43
46
  # @api private
44
- #
45
- # @since 2.5.0
46
- def initialize(executors = [], options = {})
47
+ def initialize(executors, options = {})
47
48
  @thread = nil
48
49
  @executors = executors
49
50
  @stop_semaphore = Semaphore.new
@@ -28,42 +28,38 @@ module Mongo
28
28
  class CursorReaper
29
29
  include Retryable
30
30
 
31
- # The default time interval for the cursor reaper to send pending kill cursors operations.
31
+ # The default time interval for the cursor reaper to send pending
32
+ # kill cursors operations.
32
33
  #
33
34
  # @since 2.3.0
34
35
  FREQUENCY = 1.freeze
35
36
 
36
37
  # Create a cursor reaper.
37
38
  #
38
- # @example Create a CursorReaper.
39
- # Mongo::Cluster::CursorReaper.new(cluster)
39
+ # @param [ Cluster ] cluster The cluster.
40
40
  #
41
41
  # @api private
42
- #
43
- # @since 2.3.0
44
- def initialize
42
+ def initialize(cluster)
43
+ @cluster = cluster
45
44
  @to_kill = {}
46
- @active_cursors = Set.new
45
+ @active_cursor_ids = Set.new
47
46
  @mutex = Mutex.new
48
47
  end
49
48
 
49
+ attr_reader :cluster
50
+
50
51
  # Schedule a kill cursors operation to be eventually executed.
51
52
  #
52
- # @example Schedule a kill cursors operation.
53
- # cursor_reaper.schedule_kill_cursor(id, op_spec, server)
54
- #
55
- # @param [ Integer ] id The id of the cursor to kill.
56
- # @param [ Hash ] op_spec The spec for the kill cursors op.
57
- # @param [ Mongo::Server ] server The server to send the kill cursors operation to.
53
+ # @param [ Cursor::KillSpec ] kill_spec The kill specification.
54
+ # @param [ Mongo::Server ] server The server to send the kill cursors
55
+ # operation to.
58
56
  #
59
57
  # @api private
60
- #
61
- # @since 2.3.0
62
- def schedule_kill_cursor(id, op_spec, server)
58
+ def schedule_kill_cursor(kill_spec, server)
63
59
  @mutex.synchronize do
64
- if @active_cursors.include?(id)
65
- @to_kill[server] ||= Set.new
66
- @to_kill[server] << op_spec
60
+ if @active_cursor_ids.include?(kill_spec.cursor_id)
61
+ @to_kill[server.address.seed] ||= Set.new
62
+ @to_kill[server.address.seed] << kill_spec
67
63
  end
68
64
  end
69
65
  end
@@ -87,7 +83,7 @@ module Mongo
87
83
  end
88
84
 
89
85
  @mutex.synchronize do
90
- @active_cursors << id
86
+ @active_cursor_ids << id
91
87
  end
92
88
  end
93
89
 
@@ -110,7 +106,7 @@ module Mongo
110
106
  end
111
107
 
112
108
  @mutex.synchronize do
113
- @active_cursors.delete(id)
109
+ @active_cursor_ids.delete(id)
114
110
  end
115
111
  end
116
112
 
@@ -123,33 +119,70 @@ module Mongo
123
119
  #
124
120
  # @since 2.3.0
125
121
  def kill_cursors
126
- to_kill_copy = {}
127
- active_cursors_copy = []
122
+ # TODO optimize this to batch kill cursor operations for the same
123
+ # server/database/collection instead of killing each cursor
124
+ # individually.
128
125
 
129
- @mutex.synchronize do
130
- to_kill_copy = @to_kill.dup
131
- active_cursors_copy = @active_cursors.dup
132
- @to_kill = {}
133
- end
126
+ loop do
127
+ server_address_str = nil
128
+
129
+ kill_spec = @mutex.synchronize do
130
+ # Find a server that has any cursors scheduled for destruction.
131
+ server_address_str, specs =
132
+ @to_kill.detect { |server_address_str, specs| specs.any? }
133
+
134
+ if specs.nil?
135
+ # All servers have empty specs, nothing to do.
136
+ return
137
+ end
138
+
139
+ # Note that this mutates the spec in the queue.
140
+ # If the kill cursor operation fails, we don't attempt to
141
+ # kill that cursor again.
142
+ spec = specs.take(1).tap do |arr|
143
+ specs.subtract(arr)
144
+ end.first
145
+
146
+ unless @active_cursor_ids.include?(spec.cursor_id)
147
+ # The cursor was already killed, typically because it has
148
+ # been iterated to completion. Remove the kill spec from
149
+ # our records without doing any more work.
150
+ spec = nil
151
+ end
152
+
153
+ spec
154
+ end
155
+
156
+ # If there was a spec to kill but its cursor was already killed,
157
+ # look for another spec.
158
+ next unless kill_spec
159
+
160
+ # We could also pass kill_spec directly into the KillCursors
161
+ # operation, though this would make that operation have a
162
+ # different API from all of the other ones which accept hashes.
163
+ spec = {
164
+ cursor_ids: [kill_spec.cursor_id],
165
+ coll_name: kill_spec.coll_name,
166
+ db_name: kill_spec.db_name,
167
+ }
168
+ op = Operation::KillCursors.new(spec)
169
+
170
+ server = cluster.servers.detect do |server|
171
+ server.address.seed == server_address_str
172
+ end
173
+
174
+ unless server
175
+ # TODO We currently don't have a server for the address that the
176
+ # cursor is associated with. We should leave the cursor in the
177
+ # queue to be killed at a later time (when the server comes back).
178
+ next
179
+ end
134
180
 
135
- to_kill_copy.each do |server, op_specs|
136
181
  options = {
137
182
  server_api: server.options[:server_api],
183
+ service_id: kill_spec.service_id,
138
184
  }
139
- context = Operation::Context.new(options: options)
140
- op_specs.each do |op_spec|
141
- if server.features.find_command_enabled?
142
- Cursor::Builder::KillCursorsCommand.update_cursors(op_spec, active_cursors_copy.to_a)
143
- if Cursor::Builder::KillCursorsCommand.get_cursors_list(op_spec).size > 0
144
- Operation::KillCursors.new(op_spec).execute(server, context: context)
145
- end
146
- else
147
- Cursor::Builder::OpKillCursors.update_cursors(op_spec, active_cursors_copy.to_a)
148
- if Cursor::Builder::OpKillCursors.get_cursors_list(op_spec).size > 0
149
- Operation::KillCursors.new(op_spec).execute(server, context: context)
150
- end
151
- end
152
- end
185
+ op.execute(server, context: Operation::Context.new(options: options))
153
186
  end
154
187
  end
155
188
  alias :execute :kill_cursors
@@ -105,6 +105,11 @@ class Mongo::Cluster
105
105
  end
106
106
 
107
107
  case topology
108
+ when Topology::LoadBalanced
109
+ @updated_desc = ::Mongo::Server::Description::LoadBalancer.new(
110
+ updated_desc.address,
111
+ )
112
+ update_server_descriptions
108
113
  when Topology::Single
109
114
  if topology.replica_set_name
110
115
  if updated_desc.replica_set_name != topology.replica_set_name
@@ -112,7 +117,7 @@ class Mongo::Cluster
112
117
  "Server #{updated_desc.address.to_s} has an incorrect replica set name '#{updated_desc.replica_set_name}'; expected '#{topology.replica_set_name}'"
113
118
  )
114
119
  @updated_desc = ::Mongo::Server::Description.new(updated_desc.address,
115
- {}, updated_desc.average_round_trip_time)
120
+ {}, average_round_trip_time: updated_desc.average_round_trip_time)
116
121
  update_server_descriptions
117
122
  end
118
123
  end
@@ -229,7 +234,7 @@ class Mongo::Cluster
229
234
 
230
235
  if stale_primary?
231
236
  @updated_desc = ::Mongo::Server::Description.new(updated_desc.address,
232
- {}, updated_desc.average_round_trip_time)
237
+ {}, average_round_trip_time: updated_desc.average_round_trip_time)
233
238
  update_server_descriptions
234
239
  check_if_has_primary
235
240
  return
@@ -258,7 +263,8 @@ class Mongo::Cluster
258
263
  if server.address != updated_desc.address
259
264
  if server.primary?
260
265
  server.update_description(::Mongo::Server::Description.new(
261
- server.address, {}, server.description.average_round_trip_time))
266
+ server.address, {},
267
+ average_round_trip_time: server.description.average_round_trip_time))
262
268
  end
263
269
  end
264
270
  end
@@ -67,17 +67,21 @@ module Mongo
67
67
  @server_descriptions[server.address.to_s] = server.description
68
68
  end
69
69
 
70
- begin
71
- server_descriptions.each do |address_str, desc|
72
- unless desc.unknown?
73
- desc.features.check_driver_support!
70
+ if is_a?(LoadBalanced)
71
+ @compatible = true
72
+ else
73
+ begin
74
+ server_descriptions.each do |address_str, desc|
75
+ unless desc.unknown?
76
+ desc.features.check_driver_support!
77
+ end
74
78
  end
79
+ rescue Error::UnsupportedFeatures => e
80
+ @compatible = false
81
+ @compatibility_error = e
82
+ else
83
+ @compatible = true
75
84
  end
76
- rescue Error::UnsupportedFeatures => e
77
- @compatible = false
78
- @compatibility_error = e
79
- else
80
- @compatible = true
81
85
  end
82
86
 
83
87
  @have_data_bearing_servers = false
@@ -0,0 +1,102 @@
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 Cluster
20
+ module Topology
21
+
22
+ # Defines behavior for when a cluster is in load-balanced topology.
23
+ class LoadBalanced < Base
24
+
25
+ # The display name for the topology.
26
+ NAME = 'LoadBalanced'.freeze
27
+
28
+ # Get the display name.
29
+ #
30
+ # @return [ String ] The display name.
31
+ def display_name
32
+ self.class.name.gsub(/.*::/, '')
33
+ end
34
+
35
+ # @note This method is experimental and subject to change.
36
+ #
37
+ # @api experimental
38
+ def summary
39
+ details = server_descriptions.keys.join(',')
40
+ "#{display_name}[#{details}]"
41
+ end
42
+
43
+ # Determine if the topology would select a readable server for the
44
+ # provided candidates and read preference.
45
+ #
46
+ # @param [ Cluster ] cluster The cluster.
47
+ # @param [ ServerSelector ] server_selector The server
48
+ # selector.
49
+ #
50
+ # @return [ true ] A standalone always has a readable server.
51
+ def has_readable_server?(cluster, server_selector = nil); true; end
52
+
53
+ # Determine if the topology would select a writable server for the
54
+ # provided candidates.
55
+ #
56
+ # @param [ Cluster ] cluster The cluster.
57
+ #
58
+ # @return [ true ] A standalone always has a writable server.
59
+ def has_writable_server?(cluster); true; end
60
+
61
+ # Returns whether this topology is one of the replica set ones.
62
+ #
63
+ # @return [ false ] Always false.
64
+ def replica_set?; false; end
65
+
66
+ # Select appropriate servers for this topology.
67
+ #
68
+ # @param [ Array<Server> ] servers The known servers.
69
+ #
70
+ # @return [ Array<Server> ] All of the known servers.
71
+ def servers(servers, name = nil)
72
+ servers
73
+ end
74
+
75
+ # Returns whether this topology is sharded.
76
+ #
77
+ # @return [ false ] Always false.
78
+ def sharded?; false; end
79
+
80
+ # Returns whether this topology is Single.
81
+ #
82
+ # @return [ true ] Always false.
83
+ def single?; false; end
84
+
85
+ # Returns whether this topology is Unknown.
86
+ #
87
+ # @return [ false ] Always false.
88
+ def unknown?; false; end
89
+
90
+ private
91
+
92
+ def validate_options(options, cluster)
93
+ if cluster.servers_list.length > 1
94
+ raise ArgumentError, "Cannot instantiate a load-balanced topology with more than one server in the cluster: #{cluster.servers_list.map(&:address).map(&:seed).join(', ')}"
95
+ end
96
+
97
+ super(options, cluster)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -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