mongo 2.13.0.beta1 → 2.14.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 (339) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +50 -9
  5. data/lib/mongo.rb +13 -2
  6. data/lib/mongo/address.rb +1 -1
  7. data/lib/mongo/address/ipv4.rb +1 -1
  8. data/lib/mongo/address/ipv6.rb +1 -1
  9. data/lib/mongo/auth/aws/request.rb +31 -5
  10. data/lib/mongo/bulk_write.rb +18 -0
  11. data/lib/mongo/caching_cursor.rb +74 -0
  12. data/lib/mongo/client.rb +238 -31
  13. data/lib/mongo/cluster.rb +56 -20
  14. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  15. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  16. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  17. data/lib/mongo/cluster/topology/single.rb +2 -2
  18. data/lib/mongo/collection.rb +66 -24
  19. data/lib/mongo/collection/view.rb +24 -20
  20. data/lib/mongo/collection/view/aggregation.rb +25 -4
  21. data/lib/mongo/collection/view/builder/find_command.rb +38 -18
  22. data/lib/mongo/collection/view/explainable.rb +27 -8
  23. data/lib/mongo/collection/view/iterable.rb +72 -12
  24. data/lib/mongo/collection/view/readable.rb +19 -3
  25. data/lib/mongo/collection/view/writable.rb +55 -5
  26. data/lib/mongo/crypt/encryption_io.rb +6 -6
  27. data/lib/mongo/cursor.rb +16 -3
  28. data/lib/mongo/database.rb +37 -4
  29. data/lib/mongo/database/view.rb +18 -3
  30. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  31. data/lib/mongo/error.rb +5 -0
  32. data/lib/mongo/error/invalid_read_concern.rb +28 -0
  33. data/lib/mongo/error/invalid_server_auth_host.rb +22 -0
  34. data/lib/mongo/error/invalid_session.rb +2 -1
  35. data/lib/mongo/error/operation_failure.rb +11 -5
  36. data/lib/mongo/error/server_certificate_revoked.rb +22 -0
  37. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  38. data/lib/mongo/error/unsupported_option.rb +14 -12
  39. data/lib/mongo/event/base.rb +6 -0
  40. data/lib/mongo/grid/file.rb +5 -0
  41. data/lib/mongo/grid/file/chunk.rb +2 -0
  42. data/lib/mongo/grid/fs_bucket.rb +15 -13
  43. data/lib/mongo/grid/stream/write.rb +9 -3
  44. data/lib/mongo/index/view.rb +3 -0
  45. data/lib/mongo/lint.rb +2 -1
  46. data/lib/mongo/logger.rb +3 -3
  47. data/lib/mongo/monitoring.rb +38 -0
  48. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  49. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  50. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  51. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  52. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  53. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  54. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  55. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  56. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  57. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  58. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  59. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  60. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  61. data/lib/mongo/monitoring/publishable.rb +6 -3
  62. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  63. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  64. data/lib/mongo/operation.rb +2 -0
  65. data/lib/mongo/operation/aggregate/result.rb +9 -8
  66. data/lib/mongo/operation/collections_info/command.rb +5 -0
  67. data/lib/mongo/operation/collections_info/result.rb +18 -1
  68. data/lib/mongo/operation/delete/bulk_result.rb +2 -0
  69. data/lib/mongo/operation/delete/result.rb +3 -0
  70. data/lib/mongo/operation/explain/command.rb +4 -0
  71. data/lib/mongo/operation/explain/legacy.rb +4 -0
  72. data/lib/mongo/operation/explain/op_msg.rb +6 -0
  73. data/lib/mongo/operation/explain/result.rb +3 -0
  74. data/lib/mongo/operation/find/legacy/result.rb +2 -0
  75. data/lib/mongo/operation/find/result.rb +13 -0
  76. data/lib/mongo/operation/get_more/result.rb +3 -0
  77. data/lib/mongo/operation/indexes/result.rb +5 -0
  78. data/lib/mongo/operation/insert/bulk_result.rb +5 -0
  79. data/lib/mongo/operation/insert/result.rb +5 -0
  80. data/lib/mongo/operation/list_collections/result.rb +5 -0
  81. data/lib/mongo/operation/map_reduce/result.rb +10 -0
  82. data/lib/mongo/operation/parallel_scan/result.rb +4 -0
  83. data/lib/mongo/operation/result.rb +35 -6
  84. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
  85. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
  86. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
  87. data/lib/mongo/operation/shared/executable.rb +1 -0
  88. data/lib/mongo/operation/shared/idable.rb +2 -1
  89. data/lib/mongo/operation/shared/limited.rb +1 -0
  90. data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
  91. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
  92. data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
  93. data/lib/mongo/operation/shared/specifiable.rb +1 -0
  94. data/lib/mongo/operation/shared/write.rb +1 -0
  95. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
  96. data/lib/mongo/operation/update/legacy/result.rb +7 -0
  97. data/lib/mongo/operation/update/result.rb +8 -0
  98. data/lib/mongo/operation/users_info/result.rb +3 -0
  99. data/lib/mongo/protocol/message.rb +47 -10
  100. data/lib/mongo/protocol/msg.rb +34 -1
  101. data/lib/mongo/protocol/query.rb +36 -0
  102. data/lib/mongo/protocol/serializers.rb +5 -2
  103. data/lib/mongo/query_cache.rb +242 -0
  104. data/lib/mongo/retryable.rb +8 -1
  105. data/lib/mongo/server.rb +15 -4
  106. data/lib/mongo/server/app_metadata.rb +27 -3
  107. data/lib/mongo/server/connection.rb +4 -4
  108. data/lib/mongo/server/connection_base.rb +38 -12
  109. data/lib/mongo/server/connection_common.rb +2 -2
  110. data/lib/mongo/server/connection_pool.rb +3 -0
  111. data/lib/mongo/server/description.rb +13 -1
  112. data/lib/mongo/server/monitor.rb +76 -44
  113. data/lib/mongo/server/monitor/connection.rb +57 -9
  114. data/lib/mongo/server/pending_connection.rb +14 -4
  115. data/lib/mongo/server/push_monitor.rb +173 -0
  116. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  117. data/lib/mongo/server_selector.rb +0 -1
  118. data/lib/mongo/server_selector/base.rb +583 -1
  119. data/lib/mongo/server_selector/nearest.rb +1 -6
  120. data/lib/mongo/server_selector/primary.rb +1 -6
  121. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  122. data/lib/mongo/server_selector/secondary.rb +1 -6
  123. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  124. data/lib/mongo/session.rb +7 -1
  125. data/lib/mongo/socket.rb +26 -12
  126. data/lib/mongo/socket/ocsp_cache.rb +97 -0
  127. data/lib/mongo/socket/ocsp_verifier.rb +368 -0
  128. data/lib/mongo/socket/ssl.rb +46 -25
  129. data/lib/mongo/socket/tcp.rb +1 -1
  130. data/lib/mongo/srv/monitor.rb +7 -13
  131. data/lib/mongo/srv/resolver.rb +14 -10
  132. data/lib/mongo/timeout.rb +2 -0
  133. data/lib/mongo/topology_version.rb +9 -0
  134. data/lib/mongo/uri.rb +21 -390
  135. data/lib/mongo/uri/options_mapper.rb +582 -0
  136. data/lib/mongo/uri/srv_protocol.rb +3 -2
  137. data/lib/mongo/utils.rb +73 -0
  138. data/lib/mongo/version.rb +1 -1
  139. data/spec/NOTES.aws-auth.md +12 -7
  140. data/spec/README.aws-auth.md +2 -2
  141. data/spec/README.md +63 -1
  142. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  143. data/spec/integration/bson_symbol_spec.rb +4 -2
  144. data/spec/integration/bulk_write_spec.rb +67 -0
  145. data/spec/integration/change_stream_examples_spec.rb +6 -2
  146. data/spec/integration/change_stream_spec.rb +1 -1
  147. data/spec/integration/check_clean_slate_spec.rb +16 -0
  148. data/spec/integration/client_authentication_options_spec.rb +92 -28
  149. data/spec/integration/client_construction_spec.rb +1 -0
  150. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +9 -5
  151. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  152. data/spec/integration/connection_pool_populator_spec.rb +4 -2
  153. data/spec/integration/connection_spec.rb +7 -4
  154. data/spec/integration/crud_spec.rb +4 -4
  155. data/spec/integration/cursor_reaping_spec.rb +54 -18
  156. data/spec/integration/docs_examples_spec.rb +6 -0
  157. data/spec/integration/fork_reconnect_spec.rb +56 -1
  158. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  159. data/spec/integration/heartbeat_events_spec.rb +4 -23
  160. data/spec/integration/ocsp_connectivity_spec.rb +26 -0
  161. data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
  162. data/spec/integration/ocsp_verifier_spec.rb +334 -0
  163. data/spec/integration/query_cache_spec.rb +1045 -0
  164. data/spec/integration/query_cache_transactions_spec.rb +190 -0
  165. data/spec/integration/read_concern_spec.rb +1 -1
  166. data/spec/integration/retryable_errors_spec.rb +1 -1
  167. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
  168. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +4 -2
  169. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  170. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  171. data/spec/integration/sdam_error_handling_spec.rb +122 -15
  172. data/spec/integration/sdam_events_spec.rb +80 -6
  173. data/spec/integration/sdam_prose_spec.rb +64 -0
  174. data/spec/integration/server_monitor_spec.rb +25 -1
  175. data/spec/integration/server_selection_spec.rb +36 -0
  176. data/spec/integration/size_limit_spec.rb +23 -5
  177. data/spec/integration/srv_monitoring_spec.rb +38 -3
  178. data/spec/integration/srv_spec.rb +56 -0
  179. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  180. data/spec/integration/transactions_examples_spec.rb +17 -7
  181. data/spec/integration/zlib_compression_spec.rb +25 -0
  182. data/spec/lite_spec_helper.rb +20 -9
  183. data/spec/mongo/address_spec.rb +1 -1
  184. data/spec/mongo/auth/aws/request_region_spec.rb +42 -0
  185. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  186. data/spec/mongo/auth/scram_spec.rb +1 -1
  187. data/spec/mongo/auth/user_spec.rb +1 -1
  188. data/spec/mongo/bulk_write_spec.rb +2 -2
  189. data/spec/mongo/caching_cursor_spec.rb +70 -0
  190. data/spec/mongo/client_construction_spec.rb +386 -3
  191. data/spec/mongo/client_encryption_spec.rb +16 -10
  192. data/spec/mongo/client_spec.rb +85 -3
  193. data/spec/mongo/cluster/topology/replica_set_spec.rb +53 -10
  194. data/spec/mongo/cluster/topology/sharded_spec.rb +1 -1
  195. data/spec/mongo/cluster/topology/single_spec.rb +19 -8
  196. data/spec/mongo/cluster/topology/unknown_spec.rb +1 -1
  197. data/spec/mongo/cluster/topology_spec.rb +1 -1
  198. data/spec/mongo/cluster_spec.rb +37 -35
  199. data/spec/mongo/collection/view/change_stream_resume_spec.rb +7 -7
  200. data/spec/mongo/collection/view/explainable_spec.rb +87 -4
  201. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
  202. data/spec/mongo/collection/view/readable_spec.rb +36 -0
  203. data/spec/mongo/collection_spec.rb +572 -0
  204. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  205. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  206. data/spec/mongo/crypt/binary_spec.rb +1 -6
  207. data/spec/mongo/crypt/binding/binary_spec.rb +1 -6
  208. data/spec/mongo/crypt/binding/context_spec.rb +2 -7
  209. data/spec/mongo/crypt/binding/helpers_spec.rb +1 -6
  210. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +2 -7
  211. data/spec/mongo/crypt/binding/status_spec.rb +1 -6
  212. data/spec/mongo/crypt/binding/version_spec.rb +1 -6
  213. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  214. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  215. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
  216. data/spec/mongo/crypt/status_spec.rb +1 -6
  217. data/spec/mongo/database_spec.rb +353 -8
  218. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  219. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  220. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  221. data/spec/mongo/index/view_spec.rb +148 -2
  222. data/spec/mongo/logger_spec.rb +13 -11
  223. data/spec/mongo/monitoring/event/server_closed_spec.rb +1 -1
  224. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  225. data/spec/mongo/monitoring/event/server_opening_spec.rb +1 -1
  226. data/spec/mongo/monitoring/event/topology_changed_spec.rb +1 -1
  227. data/spec/mongo/monitoring/event/topology_closed_spec.rb +1 -1
  228. data/spec/mongo/monitoring/event/topology_opening_spec.rb +1 -1
  229. data/spec/mongo/operation/delete/op_msg_spec.rb +3 -3
  230. data/spec/mongo/operation/insert/command_spec.rb +2 -2
  231. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -3
  232. data/spec/mongo/operation/read_preference_op_msg_spec.rb +1 -1
  233. data/spec/mongo/operation/update/command_spec.rb +2 -2
  234. data/spec/mongo/operation/update/op_msg_spec.rb +3 -3
  235. data/spec/mongo/protocol/msg_spec.rb +10 -0
  236. data/spec/mongo/query_cache_spec.rb +280 -0
  237. data/spec/mongo/semaphore_spec.rb +51 -0
  238. data/spec/mongo/server/app_metadata_shared.rb +82 -2
  239. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  240. data/spec/mongo/server/connection_pool_spec.rb +7 -3
  241. data/spec/mongo/server/connection_spec.rb +15 -8
  242. data/spec/mongo/server/description_spec.rb +18 -0
  243. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  244. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  245. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  246. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  247. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  248. data/spec/mongo/server_selector_spec.rb +6 -6
  249. data/spec/mongo/session_spec.rb +35 -0
  250. data/spec/mongo/socket/ssl_spec.rb +4 -4
  251. data/spec/mongo/socket_spec.rb +1 -1
  252. data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
  253. data/spec/mongo/uri_option_parsing_spec.rb +11 -11
  254. data/spec/mongo/uri_spec.rb +68 -41
  255. data/spec/mongo/utils_spec.rb +39 -0
  256. data/spec/runners/auth.rb +3 -0
  257. data/spec/runners/change_streams/test.rb +3 -3
  258. data/spec/runners/cmap.rb +1 -1
  259. data/spec/runners/command_monitoring.rb +3 -34
  260. data/spec/runners/connection_string.rb +35 -124
  261. data/spec/runners/crud/context.rb +9 -5
  262. data/spec/runners/crud/operation.rb +59 -27
  263. data/spec/runners/crud/spec.rb +0 -8
  264. data/spec/runners/crud/test.rb +1 -1
  265. data/spec/runners/crud/test_base.rb +0 -19
  266. data/spec/runners/sdam.rb +2 -2
  267. data/spec/runners/server_selection.rb +242 -28
  268. data/spec/runners/transactions.rb +12 -12
  269. data/spec/runners/transactions/operation.rb +151 -25
  270. data/spec/runners/transactions/test.rb +62 -18
  271. data/spec/shared/LICENSE +20 -0
  272. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  273. data/spec/shared/lib/mrss/constraints.rb +303 -0
  274. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  275. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  276. data/spec/spec_helper.rb +3 -1
  277. data/spec/spec_tests/cmap_spec.rb +7 -3
  278. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  279. data/spec/spec_tests/crud_spec.rb +1 -1
  280. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -9
  281. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  282. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  283. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  284. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  285. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  288. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  289. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  290. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  291. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  292. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  293. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  294. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  295. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  296. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  297. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  298. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  299. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
  300. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
  301. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  302. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  303. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  304. data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
  305. data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
  306. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  307. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
  308. data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
  309. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
  310. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  311. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  312. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  313. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  314. data/spec/spec_tests/server_selection_spec.rb +4 -116
  315. data/spec/spec_tests/uri_options_spec.rb +31 -33
  316. data/spec/stress/cleanup_spec.rb +17 -2
  317. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  318. data/spec/stress/fork_reconnect_stress_spec.rb +1 -1
  319. data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
  320. data/spec/support/certificates/atlas-ocsp.crt +41 -0
  321. data/spec/support/client_registry.rb +1 -0
  322. data/spec/support/client_registry_macros.rb +11 -2
  323. data/spec/support/cluster_config.rb +4 -0
  324. data/spec/support/common_shortcuts.rb +45 -0
  325. data/spec/support/constraints.rb +6 -253
  326. data/spec/support/event_subscriber.rb +123 -33
  327. data/spec/support/keyword_struct.rb +26 -0
  328. data/spec/support/matchers.rb +16 -0
  329. data/spec/support/ocsp +1 -0
  330. data/spec/support/session_registry.rb +52 -0
  331. data/spec/support/shared/server_selector.rb +13 -1
  332. data/spec/support/spec_config.rb +60 -13
  333. data/spec/support/spec_setup.rb +1 -1
  334. data/spec/support/utils.rb +84 -1
  335. metadata +1027 -937
  336. metadata.gz.sig +0 -0
  337. data/lib/mongo/server_selector/selectable.rb +0 -560
  338. data/spec/runners/sdam_monitoring.rb +0 -89
  339. data/spec/support/lite_constraints.rb +0 -141
@@ -156,7 +156,9 @@ module Mongo
156
156
  operation_id = Monitoring.next_operation_id
157
157
  command_started(address, operation_id, message.payload,
158
158
  socket_object_id: socket.object_id, connection_id: id,
159
- connection_generation: generation)
159
+ connection_generation: generation,
160
+ server_connection_id: description.server_connection_id,
161
+ )
160
162
  start = Time.now
161
163
  result = nil
162
164
  begin
@@ -184,9 +186,6 @@ module Mongo
184
186
  end
185
187
 
186
188
  def serialize(message, client, buffer = BSON::ByteBuffer.new)
187
- start_size = 0
188
- final_message = message.maybe_compress(compressor, options[:zlib_compression_level])
189
-
190
189
  # Driver specifications only mandate the fixed 16MiB limit for
191
190
  # serialized BSON documents. However, the server returns its
192
191
  # active serialized BSON document size limit in the ismaster response,
@@ -205,18 +204,45 @@ module Mongo
205
204
  if message.bulk_write?
206
205
  # Make the new maximum size equal to the specified reduced size
207
206
  # limit plus the 16KiB overhead allowance.
208
- max_bson_size = REDUCED_MAX_BSON_SIZE + MAX_BSON_COMMAND_OVERHEAD
207
+ max_bson_size = REDUCED_MAX_BSON_SIZE
209
208
  end
210
- else
211
- max_bson_size += MAX_BSON_COMMAND_OVERHEAD
212
209
  end
213
210
 
214
- final_message.serialize(buffer, max_bson_size)
215
- if max_message_size &&
216
- (buffer.length - start_size) > max_message_size
217
- then
218
- raise Error::MaxMessageSize.new(max_message_size)
211
+ # RUBY-2234: It is necessary to check that the message size does not
212
+ # exceed the maximum bson object size before compressing and serializing
213
+ # the final message.
214
+ #
215
+ # This is to avoid the case where the user performs a bulk write
216
+ # larger than 16MiB which, when compressed, becomes smaller than 16MiB.
217
+ # If the driver does not split the bulk writes prior to compression,
218
+ # the entire operation will be sent to the server, which will raise an
219
+ # error because the uncompressed operation exceeds the maximum bson size.
220
+ #
221
+ # To address this problem, we serialize the message prior to compression
222
+ # and raise an exception if the serialized message exceeds the maximum
223
+ # bson size.
224
+ if max_message_size
225
+ # Create a separate buffer that contains the un-compressed message
226
+ # for the purpose of checking its size. Write any pre-existing contents
227
+ # from the original buffer into the temporary one.
228
+ temp_buffer = BSON::ByteBuffer.new
229
+
230
+ # TODO: address the fact that this line mutates the buffer.
231
+ temp_buffer.put_bytes(buffer.get_bytes(buffer.length))
232
+
233
+ message.serialize(temp_buffer, max_bson_size, MAX_BSON_COMMAND_OVERHEAD)
234
+ if temp_buffer.length > max_message_size
235
+ raise Error::MaxMessageSize.new(max_message_size)
236
+ end
219
237
  end
238
+
239
+ # RUBY-2335: When the un-compressed message is smaller than the maximum
240
+ # bson size limit, the message will be serialized twice. The operations
241
+ # layer should be refactored to allow compression on an already-
242
+ # serialized message.
243
+ final_message = message.maybe_compress(compressor, options[:zlib_compression_level])
244
+ final_message.serialize(buffer, max_bson_size, MAX_BSON_COMMAND_OVERHEAD)
245
+
220
246
  buffer
221
247
  end
222
248
  end
@@ -105,8 +105,8 @@ module Mongo
105
105
  options.select { |k, v| k.to_s.start_with?('ssl') }
106
106
  else
107
107
  # Due to the way options are propagated from the client, if we
108
- # decide that we don't want to use TLS we need to have the ssl
109
- # options explicitly set to false or the value provided to the
108
+ # decide that we don't want to use TLS we need to have the :ssl
109
+ # option explicitly set to false or the value provided to the
110
110
  # connection might be overwritten by the default inherited from
111
111
  # the client.
112
112
  {ssl: false}
@@ -766,6 +766,9 @@ module Mongo
766
766
  connection.disconnect!(reason: :error)
767
767
  raise
768
768
  end
769
+ rescue Error::SocketError, Error::SocketTimeoutError => exc
770
+ @server.unknown!(generation: exc.generation, stop_push_monitor: true)
771
+ raise
769
772
  end
770
773
 
771
774
  def check_invariants
@@ -182,13 +182,20 @@ module Mongo
182
182
  # @since 2.5.0
183
183
  LOGICAL_SESSION_TIMEOUT_MINUTES = 'logicalSessionTimeoutMinutes'.freeze
184
184
 
185
+ # Constant for reading connectionId info from config.
186
+ #
187
+ # @api private
188
+ CONNECTION_ID = 'connectionId'.freeze
189
+
185
190
  # Fields to exclude when comparing two descriptions.
186
191
  #
187
192
  # @since 2.0.6
188
193
  EXCLUDE_FOR_COMPARISON = [ LOCAL_TIME,
189
194
  LAST_WRITE,
190
195
  OPERATION_TIME,
191
- Operation::CLUSTER_TIME ].freeze
196
+ Operation::CLUSTER_TIME,
197
+ CONNECTION_ID,
198
+ ].freeze
192
199
 
193
200
  # Instantiate the new server description from the result of the ismaster
194
201
  # command.
@@ -755,6 +762,11 @@ module Mongo
755
762
  # @since 2.7.0
756
763
  attr_reader :last_update_time
757
764
 
765
+ # @api experimental
766
+ def server_connection_id
767
+ config['connectionId']
768
+ end
769
+
758
770
  # Check equality of two descriptions.
759
771
  #
760
772
  # @example Check description equality.
@@ -77,7 +77,9 @@ module Mongo
77
77
  @monitoring = monitoring
78
78
  @options = options.freeze
79
79
  @mutex = Mutex.new
80
+ @sdam_mutex = Mutex.new
80
81
  @next_earliest_scan = @next_wanted_scan = Time.now
82
+ @update_mutex = Mutex.new
81
83
  end
82
84
 
83
85
  # @return [ Server ] server The server that this monitor is monitoring.
@@ -109,6 +111,14 @@ module Mongo
109
111
  # @return [ Monitoring ] monitoring The monitoring.
110
112
  attr_reader :monitoring
111
113
 
114
+ # @return [ Server::PushMonitor | nil ] The push monitor, if one is being
115
+ # used.
116
+ def push_monitor
117
+ @update_mutex.synchronize do
118
+ @push_monitor
119
+ end
120
+ end
121
+
112
122
  # Runs the server monitor. Refreshing happens on a separate thread per
113
123
  # server.
114
124
  #
@@ -120,9 +130,19 @@ module Mongo
120
130
  # @since 2.0.0
121
131
  def do_work
122
132
  scan!
123
- delta = @next_wanted_scan - Time.now
124
- if delta > 0
125
- server.scan_semaphore.wait(delta)
133
+ # @next_wanted_scan may be updated by the push monitor.
134
+ # However we need to check for termination flag so that the monitor
135
+ # thread exits when requested.
136
+ loop do
137
+ delta = @next_wanted_scan - Time.now
138
+ if delta > 0
139
+ signaled = server.scan_semaphore.wait(delta)
140
+ if signaled || @stop_requested
141
+ break
142
+ end
143
+ else
144
+ break
145
+ end
126
146
  end
127
147
  end
128
148
 
@@ -133,6 +153,8 @@ module Mongo
133
153
  #
134
154
  # @api public for backwards compatibility only
135
155
  def stop!
156
+ stop_push_monitor!
157
+
136
158
  # Forward super's return value
137
159
  super.tap do
138
160
  # Important: disconnect should happen after the background thread
@@ -141,6 +163,15 @@ module Mongo
141
163
  end
142
164
  end
143
165
 
166
+ def stop_push_monitor!
167
+ @update_mutex.synchronize do
168
+ if @push_monitor
169
+ @push_monitor.stop!
170
+ @push_monitor = nil
171
+ end
172
+ end
173
+ end
174
+
144
175
  # Perform a check of the server with throttling, and update
145
176
  # the server's description and average round trip time.
146
177
  #
@@ -168,19 +199,27 @@ module Mongo
168
199
 
169
200
  result = do_scan
170
201
 
202
+ run_sdam_flow(result)
203
+ end
204
+ end
205
+
206
+ def run_sdam_flow(result, awaited: false)
207
+ @sdam_mutex.synchronize do
171
208
  old_description = server.description
172
209
 
173
210
  new_description = Description.new(server.address, result,
174
211
  server.round_trip_time_averager.average_round_trip_time)
175
212
 
176
- server.cluster.run_sdam_flow(server.description, new_description)
213
+ server.cluster.run_sdam_flow(server.description, new_description, awaited: awaited)
177
214
 
178
215
  server.description.tap do |new_description|
179
- if new_description.unknown? && !old_description.unknown?
180
- @next_earliest_scan = @next_wanted_scan = Time.now
181
- else
182
- @next_earliest_scan = Time.now + MIN_SCAN_INTERVAL
183
- @next_wanted_scan = Time.now + heartbeat_interval
216
+ unless awaited
217
+ if new_description.unknown? && !old_description.unknown?
218
+ @next_earliest_scan = @next_wanted_scan = Time.now
219
+ else
220
+ @next_earliest_scan = Time.now + MIN_SCAN_INTERVAL
221
+ @next_wanted_scan = Time.now + heartbeat_interval
222
+ end
184
223
  end
185
224
  end
186
225
  end
@@ -209,44 +248,19 @@ module Mongo
209
248
  end
210
249
 
211
250
  def do_scan
212
- if monitoring.monitoring?
213
- monitoring.started(
214
- Monitoring::SERVER_HEARTBEAT,
215
- Monitoring::Event::ServerHeartbeatStarted.new(server.address)
216
- )
217
- end
218
-
219
- # The duration we publish in heartbeat succeeded/failed events is
220
- # the time spent on the entire heartbeat. This could include time
221
- # to connect the socket (including TLS handshake), not just time
222
- # spent on ismaster call itself.
223
- # The spec at https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring-monitoring.rst
224
- # requires that the duration exposed here start from "sending the
225
- # message" (ismaster). This requirement does not make sense if,
226
- # for example, we were never able to connect to the server at all
227
- # and thus ismaster was never sent.
228
- start_time = Time.now
229
-
230
251
  begin
231
- result = ismaster
232
- rescue => exc
233
- log_warn("Error running ismaster on #{server.address}: #{exc.class}: #{exc}:\n#{exc.backtrace[0..5].join("\n")}")
234
- if monitoring.monitoring?
235
- monitoring.failed(
236
- Monitoring::SERVER_HEARTBEAT,
237
- Monitoring::Event::ServerHeartbeatFailed.new(server.address, Time.now-start_time, exc)
238
- )
239
- end
240
- result = {}
241
- else
242
- if monitoring.monitoring?
243
- monitoring.succeeded(
244
- Monitoring::SERVER_HEARTBEAT,
245
- Monitoring::Event::ServerHeartbeatSucceeded.new(server.address, Time.now-start_time)
246
- )
252
+ monitoring.publish_heartbeat(server) do
253
+ ismaster
247
254
  end
255
+ rescue => exc
256
+ msg = "Error running ismaster on #{server.address}"
257
+ Utils.warn_bg_exception(msg, exc,
258
+ logger: options[:logger],
259
+ log_prefix: options[:log_prefix],
260
+ bg_error_backtrace: options[:bg_error_backtrace],
261
+ )
262
+ {}
248
263
  end
249
- result
250
264
  end
251
265
 
252
266
  def ismaster
@@ -274,6 +288,24 @@ module Mongo
274
288
  connection.handshake!
275
289
  end
276
290
  @connection = connection
291
+ if result['topologyVersion']
292
+ # Successful response, server 4.4+
293
+ @update_mutex.synchronize do
294
+ @push_monitor ||= PushMonitor.new(
295
+ self,
296
+ TopologyVersion.new(result['topologyVersion']),
297
+ monitoring,
298
+ **Utils.shallow_symbolize_keys(options.merge(
299
+ socket_timeout: heartbeat_interval + connection.socket_timeout,
300
+ )),
301
+ )
302
+ end
303
+ push_monitor.run!
304
+ else
305
+ # Failed response or pre-4.4 server
306
+ stop_push_monitor!
307
+ end
308
+ result
277
309
  end
278
310
  result
279
311
  end
@@ -118,9 +118,11 @@ module Mongo
118
118
  options[:connect_timeout] || Server::CONNECT_TIMEOUT
119
119
  end
120
120
 
121
+ attr_reader :server_connection_id
122
+
121
123
  # Sends a message and returns the result.
122
124
  #
123
- # @param [ Protocol::Message ] The message to send.
125
+ # @param [ Protocol::Message ] message The message to send.
124
126
  #
125
127
  # @return [ Protocol::Message ] The result.
126
128
  def dispatch(message)
@@ -129,17 +131,45 @@ module Mongo
129
131
 
130
132
  # Sends a preserialized message and returns the result.
131
133
  #
132
- # @param [ String ] The serialized message to send.
134
+ # @param [ String ] bytes The serialized message to send.
135
+ #
136
+ # @option opts [ Numeric ] :read_socket_timeout The timeout to use for
137
+ # each read operation.
133
138
  #
134
139
  # @return [ Protocol::Message ] The result.
135
- def dispatch_bytes(bytes)
140
+ def dispatch_bytes(bytes, **opts)
141
+ write_bytes(bytes)
142
+ read_response(
143
+ socket_timeout: opts[:read_socket_timeout],
144
+ )
145
+ end
146
+
147
+ def write_bytes(bytes)
136
148
  unless connected?
137
149
  raise ArgumentError, "Trying to dispatch on an unconnected connection #{self}"
138
150
  end
139
151
 
140
- add_server_diagnostics do
141
- socket.write(bytes)
142
- Protocol::Message.deserialize(socket)
152
+ add_server_connection_id do
153
+ add_server_diagnostics do
154
+ socket.write(bytes)
155
+ end
156
+ end
157
+ end
158
+
159
+ # @option opts [ Numeric ] :socket_timeout The timeout to use for
160
+ # each read operation.
161
+ def read_response(**opts)
162
+ unless connected?
163
+ raise ArgumentError, "Trying to read on an unconnected connection #{self}"
164
+ end
165
+
166
+ add_server_connection_id do
167
+ add_server_diagnostics do
168
+ Protocol::Message.deserialize(socket,
169
+ Protocol::Message::MAX_MESSAGE_SIZE,
170
+ nil,
171
+ **opts)
172
+ end
143
173
  end
144
174
  end
145
175
 
@@ -184,7 +214,7 @@ module Mongo
184
214
  # @since 2.0.0
185
215
  def disconnect!(options = nil)
186
216
  if socket
187
- socket.close
217
+ socket.close rescue nil
188
218
  @socket = nil
189
219
  end
190
220
  true
@@ -200,11 +230,29 @@ module Mongo
200
230
  message = dispatch_bytes(payload)
201
231
  reply = message.documents.first
202
232
  set_compressor!(reply)
233
+ @server_connection_id = reply['connectionId']
203
234
  reply
204
- rescue => e
205
- log_warn("Failed to handshake with #{address}: #{e.class}: #{e}:\n#{e.backtrace[0..5].join("\n")}")
235
+ rescue => exc
236
+ msg = "Failed to handshake with #{address}"
237
+ Utils.warn_bg_exception(msg, exc,
238
+ logger: options[:logger],
239
+ log_prefix: options[:log_prefix],
240
+ bg_error_backtrace: options[:bg_error_backtrace],
241
+ )
206
242
  raise
207
243
  end
244
+
245
+ private
246
+
247
+ def add_server_connection_id
248
+ yield
249
+ rescue Mongo::Error => e
250
+ if server_connection_id
251
+ note = "sconn:#{server_connection_id}"
252
+ e.add_note(note)
253
+ end
254
+ raise e
255
+ end
208
256
  end
209
257
  end
210
258
  end
@@ -116,8 +116,13 @@ module Mongo
116
116
  Protocol::Message.deserialize(socket, Protocol::Message::MAX_MESSAGE_SIZE).documents.first
117
117
  end
118
118
  end
119
- rescue => e
120
- log_warn("Failed to handshake with #{address}: #{e.class}: #{e}:\n#{e.backtrace[0..5].join("\n")}")
119
+ rescue => exc
120
+ msg = "Failed to handshake with #{address}"
121
+ Utils.warn_bg_exception(msg, exc,
122
+ logger: options[:logger],
123
+ log_prefix: options[:log_prefix],
124
+ bg_error_backtrace: options[:bg_error_backtrace],
125
+ )
121
126
  raise
122
127
  end
123
128
  end
@@ -151,8 +156,13 @@ module Mongo
151
156
  speculative_auth_result: speculative_auth_result,
152
157
  )
153
158
  auth.login
154
- rescue => e
155
- log_warn("Failed to authenticate to #{address}: #{e.class}: #{e}:\n#{e.backtrace[0..5].join("\n")}")
159
+ rescue => exc
160
+ msg = "Failed to authenticate to #{address}"
161
+ Utils.warn_bg_exception(msg, exc,
162
+ logger: options[:logger],
163
+ log_prefix: options[:log_prefix],
164
+ bg_error_backtrace: options[:bg_error_backtrace],
165
+ )
156
166
  raise
157
167
  end
158
168
  end