mongo 2.15.0 → 2.17.0

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 (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
@@ -9,6 +9,10 @@ describe Mongo::Server::Connection do
9
9
 
10
10
  clean_slate_for_all
11
11
 
12
+ let(:generation_manager) do
13
+ Mongo::Server::ConnectionPool::GenerationManager.new(server: server)
14
+ end
15
+
12
16
  let!(:address) do
13
17
  default_address
14
18
  end
@@ -41,7 +45,10 @@ describe Mongo::Server::Connection do
41
45
  let(:server_options) { SpecConfig.instance.test_options.merge(monitoring_io: false) }
42
46
  let(:server) do
43
47
  register_server(
44
- Mongo::Server.new(address, cluster, monitoring, listeners, server_options)
48
+ Mongo::Server.new(address, cluster, monitoring, listeners, server_options.merge(
49
+ # Normally the load_balancer option is set by the cluster
50
+ load_balancer: ClusterConfig.instance.topology == :load_balanced,
51
+ ))
45
52
  )
46
53
  end
47
54
 
@@ -59,6 +66,7 @@ describe Mongo::Server::Connection do
59
66
  let(:pool) do
60
67
  double('pool').tap do |pool|
61
68
  allow(pool).to receive(:close)
69
+ allow(pool).to receive(:generation_manager).and_return(generation_manager)
62
70
  end
63
71
  end
64
72
 
@@ -81,7 +89,7 @@ describe Mongo::Server::Connection do
81
89
  context 'when no socket exists' do
82
90
 
83
91
  let(:connection) do
84
- described_class.new(server, server.options)
92
+ described_class.new(server, server.options.merge(connection_pool: pool))
85
93
  end
86
94
 
87
95
  let(:result) do
@@ -226,12 +234,15 @@ describe Mongo::Server::Connection do
226
234
 
227
235
  context 'when #handshake! dependency raises a network exception' do
228
236
  let(:exception) do
229
- Mongo::Error::SocketError.new
237
+ Mongo::Error::SocketError.new.tap do |exc|
238
+ allow(exc).to receive(:service_id).and_return('fake')
239
+ end
230
240
  end
231
241
 
232
242
  let(:error) do
233
243
  # The exception is mutated when notes are added to it
234
- expect_any_instance_of(Mongo::Socket).to receive(:write).and_raise(exception.dup)
244
+ expect_any_instance_of(Mongo::Socket).to receive(:write).and_raise(exception)
245
+ allow(connection).to receive(:service_id).and_return('fake')
235
246
  begin
236
247
  connection.connect!
237
248
  rescue Exception => e
@@ -310,7 +321,7 @@ describe Mongo::Server::Connection do
310
321
  context 'when a socket exists' do
311
322
 
312
323
  let(:connection) do
313
- described_class.new(server, server.options)
324
+ described_class.new(server, server.options.merge(connection_pool: pool))
314
325
  end
315
326
 
316
327
  let(:socket) do
@@ -369,10 +380,12 @@ describe Mongo::Server::Connection do
369
380
  described_class.new(
370
381
  server,
371
382
  SpecConfig.instance.test_options.merge(
372
- :user => 'notauser',
373
- :password => 'password',
374
- :database => SpecConfig.instance.test_db,
375
- :heartbeat_frequency => 30)
383
+ user: 'notauser',
384
+ password: 'password',
385
+ database: SpecConfig.instance.test_db,
386
+ heartbeat_frequency: 30,
387
+ connection_pool: pool,
388
+ )
376
389
  )
377
390
  end
378
391
 
@@ -448,8 +461,16 @@ describe Mongo::Server::Connection do
448
461
  )
449
462
  end
450
463
 
464
+ let(:exception) do
465
+ Mongo::Error::SocketError.new.tap do |exc|
466
+ if server.load_balancer?
467
+ allow(exc).to receive(:service_id).and_return('fake')
468
+ end
469
+ end
470
+ end
471
+
451
472
  let(:error) do
452
- expect_any_instance_of(auth_mechanism).to receive(:login).and_raise(Mongo::Error::SocketError)
473
+ expect_any_instance_of(auth_mechanism).to receive(:login).and_raise(exception)
453
474
  begin
454
475
  connection.send(:connect!)
455
476
  rescue => ex
@@ -473,9 +494,11 @@ describe Mongo::Server::Connection do
473
494
  described_class.new(
474
495
  server,
475
496
  SpecConfig.instance.test_options.merge(
476
- :user => SpecConfig.instance.test_user.name,
477
- :password => SpecConfig.instance.test_user.password,
478
- :database => SpecConfig.instance.test_user.database )
497
+ user: SpecConfig.instance.test_user.name,
498
+ password: SpecConfig.instance.test_user.password,
499
+ database: SpecConfig.instance.test_user.database,
500
+ connection_pool: pool,
501
+ )
479
502
  )
480
503
  end
481
504
 
@@ -563,7 +586,7 @@ describe Mongo::Server::Connection do
563
586
  context 'when a socket is not connected' do
564
587
 
565
588
  let(:connection) do
566
- described_class.new(server, server.options)
589
+ described_class.new(server, server.options.merge(connection_pool: pool))
567
590
  end
568
591
 
569
592
  it 'does not raise an error' do
@@ -574,7 +597,7 @@ describe Mongo::Server::Connection do
574
597
  context 'when a socket is connected' do
575
598
 
576
599
  let(:connection) do
577
- described_class.new(server, server.options)
600
+ described_class.new(server, server.options.merge(connection_pool: pool))
578
601
  end
579
602
 
580
603
  before do
@@ -598,7 +621,8 @@ describe Mongo::Server::Connection do
598
621
  described_class.new(
599
622
  server,
600
623
  SpecConfig.instance.test_options.merge(
601
- :database => SpecConfig.instance.test_user.database,
624
+ database: SpecConfig.instance.test_user.database,
625
+ connection_pool: pool,
602
626
  ).merge(Mongo::Utils.shallow_symbolize_keys(Mongo::Client.canonicalize_ruby_options(
603
627
  SpecConfig.instance.credentials_or_external_user(
604
628
  user: SpecConfig.instance.test_user.name,
@@ -817,8 +841,10 @@ describe Mongo::Server::Connection do
817
841
  # of the test, i.e. to avoid racing with the monitor thread
818
842
  # which may put the server back into non-unknown state before
819
843
  # we can verify that the server was marked unknown, kill off
820
- # the monitor thread
821
- server.monitor.instance_variable_get('@thread').kill
844
+ # the monitor thread.
845
+ unless ClusterConfig.instance.topology == :load_balanced
846
+ server.monitor.instance_variable_get('@thread').kill
847
+ end
822
848
  end
823
849
  end
824
850
 
@@ -844,27 +870,44 @@ describe Mongo::Server::Connection do
844
870
  expect(connection).to be_error
845
871
  end
846
872
 
847
- it 'disconnects connection pool' do
848
- expect(server.pool).to receive(:disconnect!)
849
- result
873
+ context 'in load-balanced topology' do
874
+ require_topology :load_balanced
875
+
876
+ it 'disconnects connection pool for service id' do
877
+ connection.service_id.should_not be nil
878
+
879
+ RSpec::Mocks.with_temporary_scope do
880
+ expect(server.pool).to receive(:disconnect!).with(service_id: connection.service_id)
881
+ result
882
+ end
883
+ end
884
+
885
+ it 'does not mark server unknown' do
886
+ expect(server).not_to be_unknown
887
+ result
888
+ expect(server).not_to be_unknown
889
+ end
850
890
  end
851
891
 
852
- it 'marks server unknown' do
853
- expect(server).not_to be_unknown
854
- result
855
- expect(server).to be_unknown
892
+ context 'in non-lb topologies' do
893
+ require_topology :single, :replica_set, :sharded
894
+
895
+ it 'disconnects connection pool' do
896
+ expect(server.pool).to receive(:disconnect!)
897
+ result
898
+ end
899
+
900
+ it 'marks server unknown' do
901
+ expect(server).not_to be_unknown
902
+ result
903
+ expect(server).to be_unknown
904
+ end
856
905
  end
857
906
 
858
907
  it 'does not request server scan' do
859
908
  expect(server.scan_semaphore).not_to receive(:signal)
860
909
  result
861
910
  end
862
-
863
- it 'marks server unknown' do
864
- expect(server).not_to be_unknown
865
- result
866
- expect(server).to be_unknown
867
- end
868
911
  end
869
912
 
870
913
  context 'when a socket timeout occurs' do
@@ -943,7 +986,7 @@ describe Mongo::Server::Connection do
943
986
  context 'when the socket_timeout is negative' do
944
987
 
945
988
  let(:connection) do
946
- described_class.new(server, server.options).tap do |connection|
989
+ described_class.new(server, server.options.merge(connection_pool: pool)).tap do |connection|
947
990
  connection.connect!
948
991
  end
949
992
  end
@@ -1002,7 +1045,7 @@ describe Mongo::Server::Connection do
1002
1045
  context 'when host and port are provided' do
1003
1046
 
1004
1047
  let(:connection) do
1005
- described_class.new(server, server.options)
1048
+ described_class.new(server, server.options.merge(connection_pool: pool))
1006
1049
  end
1007
1050
 
1008
1051
  it 'sets the address' do
@@ -1017,7 +1060,7 @@ describe Mongo::Server::Connection do
1017
1060
  it 'use incrementing ids' do
1018
1061
  expect(connection.id).to eq(1)
1019
1062
 
1020
- second_connection = described_class.new(server, server.options)
1063
+ second_connection = described_class.new(server, server.options.merge(connection_pool: pool))
1021
1064
  expect(second_connection.id).to eq(2)
1022
1065
  end
1023
1066
  end
@@ -1025,7 +1068,11 @@ describe Mongo::Server::Connection do
1025
1068
  context 'two pools for different servers' do
1026
1069
  let(:server2) do
1027
1070
  register_server(
1028
- Mongo::Server.new(address, cluster, monitoring, listeners, server_options)
1071
+ Mongo::Server.new(address, cluster, monitoring, listeners,
1072
+ server_options.merge(
1073
+ load_balancer: ClusterConfig.instance.topology == :load_balanced,
1074
+ )
1075
+ )
1029
1076
  )
1030
1077
  end
1031
1078
 
@@ -1119,10 +1166,11 @@ describe Mongo::Server::Connection do
1119
1166
  let(:connection) do
1120
1167
  described_class.new(
1121
1168
  server,
1122
- :user => SpecConfig.instance.test_user.name,
1123
- :password => SpecConfig.instance.test_user.password,
1124
- :database => SpecConfig.instance.test_db,
1125
- :auth_mech => :mongodb_cr,
1169
+ user: SpecConfig.instance.test_user.name,
1170
+ password: SpecConfig.instance.test_user.password,
1171
+ database: SpecConfig.instance.test_db,
1172
+ auth_mech: :mongodb_cr,
1173
+ connection_pool: pool,
1126
1174
  )
1127
1175
  end
1128
1176
 
@@ -1155,7 +1203,7 @@ describe Mongo::Server::Connection do
1155
1203
  end
1156
1204
 
1157
1205
  let(:connection) do
1158
- described_class.new(server, server.options)
1206
+ described_class.new(server, server.options.merge(connection_pool: pool))
1159
1207
  end
1160
1208
 
1161
1209
  context 'when a connect_timeout is in the options' do
@@ -1244,7 +1292,7 @@ describe Mongo::Server::Connection do
1244
1292
  describe '#app_metadata' do
1245
1293
  context 'when all options are identical to server' do
1246
1294
  let(:connection) do
1247
- described_class.new(server, server.options)
1295
+ described_class.new(server, server.options.merge(connection_pool: pool))
1248
1296
  end
1249
1297
 
1250
1298
  it 'is the same object as server app_metadata' do
@@ -1255,7 +1303,7 @@ describe Mongo::Server::Connection do
1255
1303
 
1256
1304
  context 'when auth options are identical to server' do
1257
1305
  let(:connection) do
1258
- described_class.new(server, server.options.merge(socket_timeout: 2))
1306
+ described_class.new(server, server.options.merge(socket_timeout: 2, connection_pool: pool))
1259
1307
  end
1260
1308
 
1261
1309
  it 'is the same object as server app_metadata' do
@@ -1268,7 +1316,7 @@ describe Mongo::Server::Connection do
1268
1316
  require_no_external_user
1269
1317
 
1270
1318
  let(:connection) do
1271
- described_class.new(server, server.options.merge(user: 'foo'))
1319
+ described_class.new(server, server.options.merge(user: 'foo', connection_pool: pool))
1272
1320
  end
1273
1321
 
1274
1322
  it 'is different object from server app_metadata' do
@@ -1282,4 +1330,51 @@ describe Mongo::Server::Connection do
1282
1330
  end
1283
1331
  end
1284
1332
  end
1333
+
1334
+ describe '#generation' do
1335
+
1336
+ context 'non-lb' do
1337
+ require_topology :single, :replica_set, :sharded
1338
+
1339
+ it 'is set' do
1340
+ server.with_connection do |conn|
1341
+ conn.service_id.should be nil
1342
+ conn.generation.should be_a(Integer)
1343
+ end
1344
+ end
1345
+
1346
+ context 'clean slate' do
1347
+ clean_slate
1348
+
1349
+ it 'starts from 1' do
1350
+ server.with_connection do |conn|
1351
+ conn.service_id.should be nil
1352
+ conn.generation.should == 1
1353
+ end
1354
+ end
1355
+ end
1356
+ end
1357
+
1358
+ context 'lb' do
1359
+ require_topology :load_balanced
1360
+
1361
+ it 'is set' do
1362
+ server.with_connection do |conn|
1363
+ conn.service_id.should_not be nil
1364
+ conn.generation.should be_a(Integer)
1365
+ end
1366
+ end
1367
+
1368
+ context 'clean slate' do
1369
+ clean_slate
1370
+
1371
+ it 'starts from 1' do
1372
+ server.with_connection do |conn|
1373
+ conn.service_id.should_not be nil
1374
+ conn.generation.should == 1
1375
+ end
1376
+ end
1377
+ end
1378
+ end
1379
+ end
1285
1380
  end
@@ -331,7 +331,7 @@ describe Mongo::Server::Description do
331
331
  describe '#average_round_trip_time' do
332
332
 
333
333
  let(:description) do
334
- described_class.new(address, { 'secondary' => false }, 4.5)
334
+ described_class.new(address, { 'secondary' => false }, average_round_trip_time: 4.5)
335
335
  end
336
336
 
337
337
  it 'defaults to nil' do
@@ -136,6 +136,28 @@ describe Mongo::Server::Monitor::Connection do
136
136
  end
137
137
  end
138
138
 
139
+ describe '#connect!' do
140
+
141
+ let(:options) do
142
+ SpecConfig.instance.test_options.merge(
143
+ app_metadata: monitor_app_metadata,
144
+ )
145
+ end
146
+
147
+ context 'when address resolution fails' do
148
+ let(:connection) { described_class.new(server.address, options) }
149
+
150
+ it 'propagates the exception' do
151
+ connection
152
+
153
+ expect(Socket).to receive(:getaddrinfo).and_raise(SocketError.new('Test exception'))
154
+ lambda do
155
+ connection.connect!
156
+ end.should raise_error(SocketError, 'Test exception')
157
+ end
158
+ end
159
+ end
160
+
139
161
  describe '#check_document' do
140
162
  context 'with API version' do
141
163
  let(:meta) do
@@ -186,16 +186,17 @@ describe Mongo::Server::Monitor do
186
186
  context 'when running after a stop' do
187
187
  it 'starts the thread' do
188
188
  ClientRegistry.instance.close_all_clients
189
+ sleep 1
189
190
  thread
190
- sleep 0.5
191
+ sleep 1
191
192
 
192
193
  RSpec::Mocks.with_temporary_scope do
193
194
  expect(monitor.connection).to receive(:disconnect!).and_call_original
194
195
  monitor.stop!
195
- sleep 0.5
196
+ sleep 1
196
197
  expect(thread.alive?).to be false
197
198
  new_thread = monitor.run!
198
- sleep 0.5
199
+ sleep 1
199
200
  expect(new_thread.alive?).to be(true)
200
201
  end
201
202
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Mongo::Server::PushMonitor do
7
+ before(:all) do
8
+ ClientRegistry.instance.close_all_clients
9
+ end
10
+
11
+ let(:address) do
12
+ default_address
13
+ end
14
+
15
+ let(:listeners) do
16
+ Mongo::Event::Listeners.new
17
+ end
18
+
19
+ let(:monitor_options) do
20
+ {}
21
+ end
22
+
23
+ let(:monitor_app_metadata) do
24
+ Mongo::Server::Monitor::AppMetadata.new(
25
+ server_api: SpecConfig.instance.ruby_options[:server_api],
26
+ )
27
+ end
28
+
29
+ let(:cluster) do
30
+ double('cluster').tap do |cluster|
31
+ allow(cluster).to receive(:run_sdam_flow)
32
+ allow(cluster).to receive(:heartbeat_interval).and_return(1000)
33
+ end
34
+ end
35
+
36
+ let(:server) do
37
+ Mongo::Server.new(address, cluster, Mongo::Monitoring.new, listeners,
38
+ monitoring_io: false)
39
+ end
40
+
41
+ let(:monitor) do
42
+ register_background_thread_object(
43
+ Mongo::Server::Monitor.new(server, listeners, Mongo::Monitoring.new,
44
+ SpecConfig.instance.test_options.merge(cluster: cluster).merge(monitor_options).update(
45
+ app_metadata: monitor_app_metadata,
46
+ push_monitor_app_metadata: monitor_app_metadata))
47
+ )
48
+ end
49
+
50
+ let(:topology_version) do
51
+ Mongo::TopologyVersion.new('processId' => BSON::ObjectId.new, 'counter' => 1)
52
+ end
53
+
54
+ let(:check_document) do
55
+ {hello: 1}
56
+ end
57
+
58
+ let(:push_monitor) do
59
+ described_class.new(monitor, topology_version, monitor.monitoring,
60
+ **monitor.options.merge(check_document: check_document))
61
+ end
62
+
63
+ describe '#do_work' do
64
+ it 'works' do
65
+ lambda do
66
+ push_monitor.do_work
67
+ end.should_not raise_error
68
+ end
69
+
70
+ context 'network error during check' do
71
+ it 'does not propagate the exception' do
72
+ push_monitor
73
+
74
+ expect(Socket).to receive(:getaddrinfo).and_raise(SocketError.new('Test exception'))
75
+ lambda do
76
+ push_monitor.do_work
77
+ end.should_not raise_error
78
+ end
79
+
80
+ it 'throttles checks' do
81
+ push_monitor
82
+
83
+ start = Mongo::Utils.monotonic_time
84
+
85
+ expect(Socket).to receive(:getaddrinfo).and_raise(SocketError.new('Test exception'))
86
+ lambda do
87
+ push_monitor.do_work
88
+ end.should_not raise_error
89
+
90
+ expect(Socket).to receive(:getaddrinfo).and_raise(SocketError.new('Test exception'))
91
+ lambda do
92
+ push_monitor.do_work
93
+ end.should_not raise_error
94
+
95
+ elapsed = Mongo::Utils.monotonic_time - start
96
+ elapsed.should > 0.5
97
+ end
98
+ end
99
+ end
100
+
101
+ end
@@ -202,12 +202,7 @@ describe Mongo::ServerSelector do
202
202
  describe "#select_server" do
203
203
  require_no_linting
204
204
 
205
- context 'when #select_in_replica_set returns a list of nils' do
206
-
207
- let(:servers) do
208
- [ make_server(:primary) ]
209
- end
210
-
205
+ context 'replica set topology' do
211
206
  let(:cluster) do
212
207
  double('cluster').tap do |c|
213
208
  allow(c).to receive(:connected?).and_return(true)
@@ -223,19 +218,141 @@ describe Mongo::ServerSelector do
223
218
  allow(c).to receive(:scan!).and_return(true)
224
219
  allow(c).to receive(:options).and_return(server_selection_timeout: 0.1)
225
220
  allow(c).to receive(:server_selection_semaphore).and_return(nil)
221
+ allow(topology).to receive(:compatible?).and_return(true)
226
222
  end
227
223
  end
228
224
 
229
- let(:read_pref) do
230
- described_class.get(mode: :primary).tap do |pref|
231
- allow(pref).to receive(:select_in_replica_set).and_return([ nil, nil ])
225
+ let(:primary) do
226
+ make_server(:primary).tap do |server|
227
+ allow(server).to receive(:features).and_return(double("primary features"))
232
228
  end
233
229
  end
234
230
 
235
- it 'raises a NoServerAvailable error' do
236
- expect do
237
- read_pref.select_server(cluster)
238
- end.to raise_exception(Mongo::Error::NoServerAvailable)
231
+ let(:secondary) do
232
+ make_server(:secondary).tap do |server|
233
+ allow(server).to receive(:features).and_return(double("secondary features"))
234
+ end
235
+ end
236
+
237
+ context "when #select_in_replica_set returns a list of nils" do
238
+ let(:servers) do
239
+ [ primary ]
240
+ end
241
+
242
+ let(:read_pref) do
243
+ described_class.get(mode: :primary).tap do |pref|
244
+ allow(pref).to receive(:select_in_replica_set).and_return([ nil, nil ])
245
+ end
246
+ end
247
+
248
+ it 'raises a NoServerAvailable error' do
249
+ expect do
250
+ read_pref.select_server(cluster)
251
+ end.to raise_exception(Mongo::Error::NoServerAvailable)
252
+ end
253
+ end
254
+
255
+ context "write_aggregation is true" do
256
+
257
+ before do
258
+ # It does not matter for this context whether primary supports secondary wites or not,
259
+ # but we need to mock out this call.
260
+ allow(primary.features).to receive(:merge_out_on_secondary_enabled?).and_return(false)
261
+ end
262
+
263
+ context "read preference is primary" do
264
+ let(:selector) { Mongo::ServerSelector::Primary.new }
265
+
266
+ let(:servers) do
267
+ [ primary, secondary ]
268
+ end
269
+
270
+ [true, false].each do |secondary_support_writes|
271
+ context "secondary #{secondary_support_writes ? 'supports' : 'does not support' } writes" do
272
+ it "selects a primary" do
273
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(secondary_support_writes)
274
+
275
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
276
+ end
277
+ end
278
+ end
279
+ end
280
+
281
+ context "read preference is primary preferred" do
282
+ let(:selector) { Mongo::ServerSelector::PrimaryPreferred.new }
283
+
284
+ let(:servers) do
285
+ [ primary, secondary ]
286
+ end
287
+
288
+ [true, false].each do |secondary_support_writes|
289
+ context "secondary #{secondary_support_writes ? 'supports' : 'does not support' } writes" do
290
+ it "selects a primary" do
291
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(secondary_support_writes)
292
+
293
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ context "read preference is secondary preferred" do
300
+ let(:selector) { Mongo::ServerSelector::SecondaryPreferred.new }
301
+
302
+ let(:servers) do
303
+ [ primary, secondary ]
304
+ end
305
+
306
+ context "secondary supports writes" do
307
+ it "selects a secondary" do
308
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(true)
309
+
310
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(secondary)
311
+ end
312
+ end
313
+
314
+ context "secondary does not support writes" do
315
+ it "selects a primary" do
316
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(false)
317
+
318
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
319
+ end
320
+ end
321
+ end
322
+
323
+ context "read preference is secondary" do
324
+ let(:selector) { Mongo::ServerSelector::Secondary.new }
325
+
326
+ let(:servers) do
327
+ [ primary, secondary ]
328
+ end
329
+
330
+ context "secondary supports writes" do
331
+ it "selects a secondary" do
332
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(true)
333
+
334
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(secondary)
335
+ end
336
+ end
337
+
338
+ context "secondary does not support writes" do
339
+ it "selects a primary" do
340
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(false)
341
+
342
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
343
+ end
344
+ end
345
+
346
+ context "no secondaries in cluster" do
347
+ let(:servers) do
348
+ [ primary ]
349
+ end
350
+
351
+ it "selects a primary" do
352
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
353
+ end
354
+ end
355
+ end
239
356
  end
240
357
  end
241
358
 
@@ -381,8 +498,12 @@ describe Mongo::ServerSelector do
381
498
  let(:servers) { [unknown, mongos] }
382
499
  let(:selector) { described_class.primary }
383
500
 
384
- it 'returns the mongos' do
385
- expect(selector.select_server(cluster)).to eq(mongos)
501
+ [true, false].each do |write_aggregation|
502
+ context "write_aggregation is #{write_aggregation}" do
503
+ it 'returns the mongos' do
504
+ expect(selector.select_server(cluster, write_aggregation: write_aggregation)).to eq(mongos)
505
+ end
506
+ end
386
507
  end
387
508
  end
388
509
  end