mongo 2.15.1 → 2.16.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (326) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/lib/mongo/bulk_write.rb +2 -2
  5. data/lib/mongo/client.rb +45 -5
  6. data/lib/mongo/cluster/periodic_executor.rb +4 -3
  7. data/lib/mongo/cluster/reapers/cursor_reaper.rb +76 -43
  8. data/lib/mongo/cluster/sdam_flow.rb +9 -3
  9. data/lib/mongo/cluster/topology/base.rb +13 -9
  10. data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
  11. data/lib/mongo/cluster/topology.rb +28 -8
  12. data/lib/mongo/cluster.rb +136 -51
  13. data/lib/mongo/collection/view/aggregation.rb +5 -10
  14. data/lib/mongo/collection/view/builder/aggregation.rb +6 -5
  15. data/lib/mongo/collection/view/builder/map_reduce.rb +12 -49
  16. data/lib/mongo/collection/view/builder.rb +0 -4
  17. data/lib/mongo/collection/view/iterable.rb +42 -18
  18. data/lib/mongo/collection/view/map_reduce.rb +39 -15
  19. data/lib/mongo/collection/view/readable.rb +60 -51
  20. data/lib/mongo/collection/view/writable.rb +178 -175
  21. data/lib/mongo/collection/view.rb +15 -21
  22. data/lib/mongo/collection.rb +13 -13
  23. data/lib/mongo/cursor/kill_spec.rb +38 -0
  24. data/lib/mongo/cursor.rb +62 -31
  25. data/lib/mongo/database/view.rb +1 -1
  26. data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
  27. data/lib/mongo/error/missing_service_id.rb +26 -0
  28. data/lib/mongo/error/no_service_connection_available.rb +49 -0
  29. data/lib/mongo/error/notable.rb +7 -0
  30. data/lib/mongo/error.rb +3 -0
  31. data/lib/mongo/grid/fs_bucket.rb +21 -2
  32. data/lib/mongo/id.rb +7 -5
  33. data/lib/mongo/index/view.rb +22 -41
  34. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +7 -4
  35. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  36. data/lib/mongo/monitoring/event/command_started.rb +2 -0
  37. data/lib/mongo/monitoring/publishable.rb +2 -2
  38. data/lib/mongo/operation/aggregate/command.rb +8 -0
  39. data/lib/mongo/operation/context.rb +19 -1
  40. data/lib/mongo/operation/count/command.rb +6 -0
  41. data/lib/mongo/operation/count/op_msg.rb +6 -0
  42. data/lib/mongo/operation/create/command.rb +7 -1
  43. data/lib/mongo/operation/create/op_msg.rb +7 -0
  44. data/lib/mongo/operation/create_index/command.rb +17 -1
  45. data/lib/mongo/operation/create_index/op_msg.rb +17 -4
  46. data/lib/mongo/operation/delete/command.rb +6 -3
  47. data/lib/mongo/operation/delete/legacy.rb +9 -2
  48. data/lib/mongo/operation/delete/op_msg.rb +8 -1
  49. data/lib/mongo/operation/distinct/command.rb +6 -0
  50. data/lib/mongo/operation/distinct/op_msg.rb +7 -0
  51. data/lib/mongo/operation/explain/command.rb +13 -1
  52. data/lib/mongo/operation/explain/legacy.rb +12 -5
  53. data/lib/mongo/operation/explain/op_msg.rb +9 -1
  54. data/lib/mongo/operation/find/builder/command.rb +110 -0
  55. data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +10 -14
  56. data/lib/mongo/operation/find/builder/legacy.rb +123 -0
  57. data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +31 -25
  58. data/lib/mongo/{cursor → operation/find}/builder.rb +4 -4
  59. data/lib/mongo/operation/find/command.rb +9 -0
  60. data/lib/mongo/operation/find/legacy.rb +10 -1
  61. data/lib/mongo/operation/find/op_msg.rb +12 -0
  62. data/lib/mongo/operation/find.rb +1 -0
  63. data/lib/mongo/operation/get_more/command.rb +1 -0
  64. data/lib/mongo/operation/get_more/command_builder.rb +38 -0
  65. data/lib/mongo/operation/get_more/op_msg.rb +1 -0
  66. data/lib/mongo/operation/get_more.rb +1 -0
  67. data/lib/mongo/operation/kill_cursors/command.rb +8 -0
  68. data/lib/mongo/operation/kill_cursors/command_builder.rb +35 -0
  69. data/lib/mongo/operation/kill_cursors/legacy.rb +2 -1
  70. data/lib/mongo/operation/kill_cursors/op_msg.rb +10 -0
  71. data/lib/mongo/operation/kill_cursors.rb +1 -0
  72. data/lib/mongo/operation/map_reduce/command.rb +8 -0
  73. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  74. data/lib/mongo/operation/shared/executable.rb +15 -1
  75. data/lib/mongo/operation/shared/polymorphic_operation.rb +1 -1
  76. data/lib/mongo/operation/shared/read_preference_supported.rb +3 -1
  77. data/lib/mongo/operation/shared/response_handling.rb +1 -0
  78. data/lib/mongo/operation/shared/sessions_supported.rb +12 -12
  79. data/lib/mongo/operation/shared/specifiable.rb +11 -29
  80. data/lib/mongo/operation/shared/validatable.rb +87 -0
  81. data/lib/mongo/operation/shared/write.rb +1 -1
  82. data/lib/mongo/operation/update/command.rb +6 -3
  83. data/lib/mongo/operation/update/legacy.rb +19 -11
  84. data/lib/mongo/operation/update/op_msg.rb +7 -4
  85. data/lib/mongo/operation/write_command/command.rb +51 -0
  86. data/lib/mongo/operation/write_command/op_msg.rb +43 -0
  87. data/lib/mongo/operation/write_command.rb +32 -0
  88. data/lib/mongo/operation.rb +10 -0
  89. data/lib/mongo/protocol/query.rb +35 -18
  90. data/lib/mongo/server/connection.rb +25 -3
  91. data/lib/mongo/server/connection_base.rb +12 -1
  92. data/lib/mongo/server/connection_common.rb +38 -1
  93. data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
  94. data/lib/mongo/server/connection_pool.rb +100 -27
  95. data/lib/mongo/server/description/features.rb +17 -16
  96. data/lib/mongo/server/description/load_balancer.rb +33 -0
  97. data/lib/mongo/server/description.rb +85 -6
  98. data/lib/mongo/server/monitor/connection.rb +5 -6
  99. data/lib/mongo/server/monitor.rb +2 -1
  100. data/lib/mongo/server/pending_connection.rb +47 -31
  101. data/lib/mongo/server.rb +73 -26
  102. data/lib/mongo/server_selector/base.rb +5 -1
  103. data/lib/mongo/session/session_pool.rb +11 -0
  104. data/lib/mongo/session.rb +21 -1
  105. data/lib/mongo/socket/ocsp_verifier.rb +6 -37
  106. data/lib/mongo/uri/options_mapper.rb +1 -0
  107. data/lib/mongo/uri/srv_protocol.rb +6 -8
  108. data/lib/mongo/uri.rb +18 -0
  109. data/lib/mongo/utils.rb +0 -7
  110. data/lib/mongo/version.rb +1 -1
  111. data/mongo.gemspec +1 -1
  112. data/spec/integration/auth_spec.rb +31 -1
  113. data/spec/integration/awaited_ismaster_spec.rb +1 -1
  114. data/spec/integration/bulk_write_spec.rb +1 -1
  115. data/spec/integration/change_stream_spec.rb +3 -3
  116. data/spec/integration/client_construction_spec.rb +54 -0
  117. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
  118. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
  119. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
  120. data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
  121. data/spec/integration/client_spec.rb +2 -0
  122. data/spec/integration/command_monitoring_spec.rb +1 -1
  123. data/spec/integration/command_spec.rb +1 -1
  124. data/spec/integration/connection_spec.rb +52 -35
  125. data/spec/integration/crud_spec.rb +174 -1
  126. data/spec/integration/cursor_pinning_spec.rb +121 -0
  127. data/spec/integration/cursor_reaping_spec.rb +8 -4
  128. data/spec/integration/fork_reconnect_spec.rb +1 -5
  129. data/spec/integration/get_more_spec.rb +1 -1
  130. data/spec/integration/heartbeat_events_spec.rb +1 -1
  131. data/spec/integration/map_reduce_spec.rb +77 -0
  132. data/spec/integration/query_cache_spec.rb +2 -2
  133. data/spec/integration/query_cache_transactions_spec.rb +1 -1
  134. data/spec/integration/read_concern_spec.rb +1 -1
  135. data/spec/integration/read_preference_spec.rb +1 -1
  136. data/spec/integration/reconnect_spec.rb +30 -12
  137. data/spec/integration/retryable_errors_spec.rb +1 -1
  138. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  139. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
  140. data/spec/integration/sdam_error_handling_spec.rb +5 -3
  141. data/spec/integration/sdam_events_spec.rb +35 -19
  142. data/spec/integration/sdam_prose_spec.rb +1 -1
  143. data/spec/integration/server_monitor_spec.rb +1 -0
  144. data/spec/integration/server_selector_spec.rb +22 -5
  145. data/spec/integration/server_spec.rb +2 -0
  146. data/spec/integration/srv_monitoring_spec.rb +1 -1
  147. data/spec/integration/step_down_spec.rb +1 -1
  148. data/spec/integration/transaction_pinning_spec.rb +120 -0
  149. data/spec/integration/versioned_api_examples_spec.rb +45 -0
  150. data/spec/integration/x509_auth_spec.rb +1 -1
  151. data/spec/lite_spec_helper.rb +1 -2
  152. data/spec/mongo/address/unix_spec.rb +1 -0
  153. data/spec/mongo/auth/cr_spec.rb +2 -3
  154. data/spec/mongo/auth/ldap_spec.rb +2 -3
  155. data/spec/mongo/auth/scram_spec.rb +2 -3
  156. data/spec/mongo/auth/user/view_spec.rb +1 -1
  157. data/spec/mongo/auth/x509_spec.rb +2 -3
  158. data/spec/mongo/bulk_write_spec.rb +3 -3
  159. data/spec/mongo/client_construction_spec.rb +259 -28
  160. data/spec/mongo/client_spec.rb +6 -4
  161. data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
  162. data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
  163. data/spec/mongo/cluster_spec.rb +44 -3
  164. data/spec/mongo/collection/view/aggregation_spec.rb +1 -1
  165. data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
  166. data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
  167. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  168. data/spec/mongo/collection_crud_spec.rb +7 -2
  169. data/spec/mongo/collection_ddl_spec.rb +1 -1
  170. data/spec/mongo/collection_spec.rb +1 -1
  171. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
  172. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
  173. data/spec/mongo/cursor_spec.rb +15 -5
  174. data/spec/mongo/database_spec.rb +15 -15
  175. data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
  176. data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
  177. data/spec/mongo/grid/stream/write_spec.rb +3 -9
  178. data/spec/mongo/grid/stream_spec.rb +1 -1
  179. data/spec/mongo/index/view_spec.rb +2 -2
  180. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  181. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
  182. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
  183. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  184. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  185. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  186. data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
  187. data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
  188. data/spec/mongo/operation/read_preference_op_msg_spec.rb +2 -0
  189. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  190. data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
  191. data/spec/mongo/query_cache_spec.rb +6 -2
  192. data/spec/mongo/server/connection_common_spec.rb +62 -11
  193. data/spec/mongo/server/connection_pool_spec.rb +73 -7
  194. data/spec/mongo/server/connection_spec.rb +138 -43
  195. data/spec/mongo/server/description_spec.rb +1 -1
  196. data/spec/mongo/server/monitor_spec.rb +4 -3
  197. data/spec/mongo/session/session_pool_spec.rb +42 -10
  198. data/spec/mongo/session_transaction_spec.rb +15 -30
  199. data/spec/mongo/socket/unix_spec.rb +1 -0
  200. data/spec/mongo/uri_option_parsing_spec.rb +38 -5
  201. data/spec/runners/change_streams/test.rb +1 -1
  202. data/spec/runners/cmap.rb +1 -1
  203. data/spec/runners/connection_string.rb +7 -3
  204. data/spec/runners/crud/operation.rb +5 -3
  205. data/spec/runners/crud/requirement.rb +1 -0
  206. data/spec/runners/crud.rb +1 -1
  207. data/spec/runners/sdam.rb +2 -1
  208. data/spec/runners/transactions/test.rb +2 -2
  209. data/spec/runners/unified/assertions.rb +2 -3
  210. data/spec/runners/unified/event_subscriber.rb +2 -2
  211. data/spec/runners/unified/test.rb +3 -0
  212. data/spec/runners/unified.rb +1 -1
  213. data/spec/shared/lib/mrss/constraints.rb +11 -5
  214. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  215. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  216. data/spec/shared/share/Dockerfile.erb +2 -1
  217. data/spec/shared/shlib/server.sh +70 -20
  218. data/spec/spec_tests/change_streams_spec.rb +1 -1
  219. data/spec/spec_tests/cmap_spec.rb +4 -1
  220. data/spec/spec_tests/command_monitoring_spec.rb +2 -2
  221. data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
  222. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  223. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  224. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  225. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  226. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  227. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  228. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  229. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  230. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  231. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  232. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  233. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  234. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  235. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  236. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  237. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  238. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  239. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  240. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
  241. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  242. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
  243. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  244. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
  245. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  246. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
  247. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  248. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
  249. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
  250. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
  251. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
  252. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
  253. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
  254. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
  255. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  256. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  257. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  258. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  259. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  260. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
  261. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
  262. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  263. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  264. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  265. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  266. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  267. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  268. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  269. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  270. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  271. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  272. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  273. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  274. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  275. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  276. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  277. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  278. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  279. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  280. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  281. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  282. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  283. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  284. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  285. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  286. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  287. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  288. data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
  289. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
  290. data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
  291. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
  292. data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
  293. data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
  294. data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
  295. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  296. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  297. data/spec/spec_tests/retryable_writes_spec.rb +1 -1
  298. data/spec/spec_tests/sdam_integration_spec.rb +1 -1
  299. data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
  300. data/spec/spec_tests/sdam_spec.rb +1 -1
  301. data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
  302. data/spec/spec_tests/uri_options_spec.rb +4 -4
  303. data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
  304. data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
  305. data/spec/support/certificates/atlas-ocsp.crt +127 -122
  306. data/spec/support/common_shortcuts.rb +2 -3
  307. data/spec/support/matchers.rb +13 -0
  308. data/spec/support/shared/auth_context.rb +16 -0
  309. data/spec/support/shared/session.rb +2 -2
  310. data/spec/support/spec_config.rb +9 -10
  311. data/spec/support/using_hash.rb +31 -0
  312. data/spec/support/utils.rb +1 -1
  313. data.tar.gz.sig +0 -0
  314. metadata +120 -76
  315. metadata.gz.sig +0 -0
  316. data/lib/mongo/collection/view/builder/find_command.rb +0 -173
  317. data/lib/mongo/collection/view/builder/op_query.rb +0 -94
  318. data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
  319. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
  320. data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
  321. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
  322. data/lib/mongo/server/context.rb +0 -72
  323. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
  324. data/spec/runners/unified/using_hash.rb +0 -34
  325. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
  326. data/spec/support/event_subscriber.rb +0 -221
data/lib/mongo/cluster.rb CHANGED
@@ -159,6 +159,10 @@ module Mongo
159
159
  @sdam_flow_lock = Mutex.new
160
160
  Session::SessionPool.create(self)
161
161
 
162
+ if seeds.empty? && load_balanced?
163
+ raise ArgumentError, 'Load-balanced clusters with no seeds are prohibited'
164
+ end
165
+
162
166
  # The opening topology is always unknown with no servers.
163
167
  # https://github.com/mongodb/specifications/pull/388
164
168
  opening_topology = Topology::Unknown.new(options, monitoring, self)
@@ -171,7 +175,7 @@ module Mongo
171
175
  @seeds = seeds = seeds.uniq
172
176
  servers = seeds.map do |seed|
173
177
  # Server opening events must be sent after topology change events.
174
- # Therefore separate server addition, done here before topoolgy change
178
+ # Therefore separate server addition, done here before topology change
175
179
  # event is published, from starting to monitor the server which is
176
180
  # done later.
177
181
  add(seed, monitor: false)
@@ -179,11 +183,20 @@ module Mongo
179
183
 
180
184
  if seeds.size >= 1
181
185
  # Recreate the topology to get the current server list into it
182
- @topology = topology.class.new(topology.options, topology.monitoring, self)
183
- publish_sdam_event(
184
- Monitoring::TOPOLOGY_CHANGED,
185
- Monitoring::Event::TopologyChanged.new(opening_topology, @topology)
186
- )
186
+ recreate_topology(topology, opening_topology)
187
+ end
188
+
189
+ if load_balanced?
190
+ # We are required by the specifications to produce certain SDAM events
191
+ # when in load-balanced topology.
192
+ # These events don't make a lot of sense from the standpoint of the
193
+ # driver's SDAM implementation, nor from the standpoint of the
194
+ # driver's load balancer implementation.
195
+ # They are just required boilerplate.
196
+ #
197
+ # Note that this call must be done above the monitoring_io check
198
+ # because that short-circuits the rest of the constructor.
199
+ fabricate_lb_sdam_events_and_set_server_type
187
200
  end
188
201
 
189
202
  if options[:monitoring_io] == false
@@ -203,7 +216,7 @@ module Mongo
203
216
  @connected = true
204
217
 
205
218
  if options[:cleanup] != false
206
- @cursor_reaper = CursorReaper.new
219
+ @cursor_reaper = CursorReaper.new(self)
207
220
  @socket_reaper = SocketReaper.new(self)
208
221
  @periodic_executor = PeriodicExecutor.new([
209
222
  @cursor_reaper, @socket_reaper,
@@ -212,54 +225,56 @@ module Mongo
212
225
  @periodic_executor.run!
213
226
  end
214
227
 
215
- # Need to record start time prior to starting monitoring
216
- start_monotime = Utils.monotonic_time
217
-
218
- servers.each do |server|
219
- server.start_monitoring
220
- end
228
+ unless load_balanced?
229
+ # Need to record start time prior to starting monitoring
230
+ start_monotime = Utils.monotonic_time
221
231
 
222
- if options[:scan] != false
223
- server_selection_timeout = options[:server_selection_timeout] || ServerSelector::SERVER_SELECTION_TIMEOUT
224
- # The server selection timeout can be very short especially in
225
- # tests, when the client waits for a synchronous scan before
226
- # starting server selection. Limiting the scan to server selection time
227
- # then aborts the scan before it can process even local servers.
228
- # Therefore, allow at least 3 seconds for the scan here.
229
- if server_selection_timeout < 3
230
- server_selection_timeout = 3
232
+ servers.each do |server|
233
+ server.start_monitoring
231
234
  end
232
- deadline = start_monotime + server_selection_timeout
233
- # Wait for the first scan of each server to complete, for
234
- # backwards compatibility.
235
- # If any servers are discovered during this SDAM round we are going to
236
- # wait for these servers to also be queried, and so on, up to the
237
- # server selection timeout or the 3 second minimum.
238
- loop do
239
- # Ensure we do not try to read the servers list while SDAM is running
240
- servers = @sdam_flow_lock.synchronize do
241
- servers_list.dup
242
- end
243
- if servers.all? { |server| server.last_scan_monotime && server.last_scan_monotime >= start_monotime }
244
- break
245
- end
246
- if (time_remaining = deadline - Utils.monotonic_time) <= 0
247
- break
235
+
236
+ if options[:scan] != false
237
+ server_selection_timeout = options[:server_selection_timeout] || ServerSelector::SERVER_SELECTION_TIMEOUT
238
+ # The server selection timeout can be very short especially in
239
+ # tests, when the client waits for a synchronous scan before
240
+ # starting server selection. Limiting the scan to server selection time
241
+ # then aborts the scan before it can process even local servers.
242
+ # Therefore, allow at least 3 seconds for the scan here.
243
+ if server_selection_timeout < 3
244
+ server_selection_timeout = 3
248
245
  end
249
- log_debug("Waiting for up to #{'%.2f' % time_remaining} seconds for servers to be scanned: #{summary}")
250
- # Since the semaphore may have been signaled between us checking
251
- # the servers list above and the wait call below, we should not
252
- # wait for the full remaining time - wait for up to 1 second, then
253
- # recheck the state.
254
- begin
255
- server_selection_semaphore.wait([time_remaining, 1].min)
256
- rescue ::Timeout::Error
257
- # nothing
246
+ deadline = start_monotime + server_selection_timeout
247
+ # Wait for the first scan of each server to complete, for
248
+ # backwards compatibility.
249
+ # If any servers are discovered during this SDAM round we are going to
250
+ # wait for these servers to also be queried, and so on, up to the
251
+ # server selection timeout or the 3 second minimum.
252
+ loop do
253
+ # Ensure we do not try to read the servers list while SDAM is running
254
+ servers = @sdam_flow_lock.synchronize do
255
+ servers_list.dup
256
+ end
257
+ if servers.all? { |server| server.last_scan_monotime && server.last_scan_monotime >= start_monotime }
258
+ break
259
+ end
260
+ if (time_remaining = deadline - Utils.monotonic_time) <= 0
261
+ break
262
+ end
263
+ log_debug("Waiting for up to #{'%.2f' % time_remaining} seconds for servers to be scanned: #{summary}")
264
+ # Since the semaphore may have been signaled between us checking
265
+ # the servers list above and the wait call below, we should not
266
+ # wait for the full remaining time - wait for up to 1 second, then
267
+ # recheck the state.
268
+ begin
269
+ server_selection_semaphore.wait([time_remaining, 1].min)
270
+ rescue ::Timeout::Error
271
+ # nothing
272
+ end
258
273
  end
259
274
  end
260
- end
261
275
 
262
- start_stop_srv_monitor
276
+ start_stop_srv_monitor
277
+ end
263
278
  end
264
279
 
265
280
  # Create a cluster for the provided client, for use when we don't want the
@@ -321,6 +336,14 @@ module Mongo
321
336
  def_delegators :topology, :replica_set?, :replica_set_name, :sharded?,
322
337
  :single?, :unknown?
323
338
 
339
+ # Returns whether the cluster is configured to be in the load-balanced
340
+ # topology.
341
+ #
342
+ # @return [ true | false ] Whether the topology is load-balanced.
343
+ def load_balanced?
344
+ topology.is_a?(Topology::LoadBalanced)
345
+ end
346
+
324
347
  [:register_cursor, :schedule_kill_cursor, :unregister_cursor].each do |m|
325
348
  define_method(m) do |*args|
326
349
  if options[:cleanup] != false
@@ -599,9 +622,25 @@ module Mongo
599
622
  # on 4.2+ servers).
600
623
  # @option aptions [ true | false ] :awaited Whether the updated description
601
624
  # was a result of processing an awaited hello.
625
+ # @option options [ Object ] :service_id Change state for the specified
626
+ # service id only.
602
627
  #
603
628
  # @api private
604
629
  def run_sdam_flow(previous_desc, updated_desc, options = {})
630
+ if load_balanced?
631
+ if updated_desc.config.empty?
632
+ unless options[:keep_connection_pool]
633
+ servers_list.each do |server|
634
+ # TODO should service id be taken out of updated_desc?
635
+ # We could also assert that
636
+ # options[:service_id] == updated_desc.service_id
637
+ server.clear_connection_pool(service_id: options[:service_id])
638
+ end
639
+ end
640
+ end
641
+ return
642
+ end
643
+
605
644
  @sdam_flow_lock.synchronize do
606
645
  flow = SdamFlow.new(self, previous_desc, updated_desc,
607
646
  awaited: options[:awaited])
@@ -782,8 +821,15 @@ module Mongo
782
821
  def add(host, add_options=nil)
783
822
  address = Address.new(host, options)
784
823
  if !addresses.include?(address)
785
- server = Server.new(address, self, @monitoring, event_listeners, options.merge(
786
- monitor: false))
824
+ opts = options.merge(monitor: false)
825
+ # Note that in a load-balanced topology, every server must be a
826
+ # load balancer (load_balancer: true is specified in the options)
827
+ # but this option isn't set here because we are required by the
828
+ # specifications to pretent the server started out as an unknown one
829
+ # and publish server description change event into the load balancer
830
+ # one. The actual correct description for this server will be set
831
+ # by the fabricate_lb_sdam_events_and_set_server_type method.
832
+ server = Server.new(address, self, @monitoring, event_listeners, opts)
787
833
  @update_lock.synchronize do
788
834
  # Need to recheck whether server is present in @servers, because
789
835
  # the previous check was not under a lock.
@@ -899,6 +945,10 @@ module Mongo
899
945
  #
900
946
  # @api private
901
947
  def validate_session_support!
948
+ if topology.is_a?(Topology::LoadBalanced)
949
+ return
950
+ end
951
+
902
952
  @state_change_lock.synchronize do
903
953
  @sdam_flow_lock.synchronize do
904
954
  if topology.data_bearing_servers?
@@ -982,6 +1032,41 @@ module Mongo
982
1032
  msg = "The deployment that the driver is connected to does not support sessions: #{reason}"
983
1033
  raise Error::SessionsNotSupported, msg
984
1034
  end
1035
+
1036
+ def fabricate_lb_sdam_events_and_set_server_type
1037
+ # Although there is no monitoring connection in load balanced mode,
1038
+ # we must emit the following series of SDAM events.
1039
+ server = @servers.first
1040
+ # We are guaranteed to have the server here.
1041
+ server.publish_opening_event
1042
+ server_desc = server.description
1043
+ # This is where a load balancer actually gets its correct server
1044
+ # description.
1045
+ server.update_description(
1046
+ Server::Description.new(server.address, {},
1047
+ load_balancer: true,
1048
+ force_load_balancer: options[:connect] == :load_balanced,
1049
+ )
1050
+ )
1051
+ publish_sdam_event(
1052
+ Monitoring::SERVER_DESCRIPTION_CHANGED,
1053
+ Monitoring::Event::ServerDescriptionChanged.new(
1054
+ server.address,
1055
+ topology,
1056
+ server_desc,
1057
+ server.description
1058
+ )
1059
+ )
1060
+ recreate_topology(topology, topology)
1061
+ end
1062
+
1063
+ def recreate_topology(new_topology_template, previous_topology)
1064
+ @topology = topology.class.new(new_topology_template.options, new_topology_template.monitoring, self)
1065
+ publish_sdam_event(
1066
+ Monitoring::TOPOLOGY_CHANGED,
1067
+ Monitoring::Event::TopologyChanged.new(previous_topology, @topology)
1068
+ )
1069
+ end
985
1070
  end
986
1071
  end
987
1072
 
@@ -121,10 +121,12 @@ module Mongo
121
121
  end
122
122
 
123
123
  def valid_server?(server)
124
- description = server.with_connection do |connection|
125
- connection.description
124
+ if secondary_ok?
125
+ true
126
+ else
127
+ description = server.description
128
+ description.standalone? || description.mongos? || description.primary? || description.load_balancer?
126
129
  end
127
- description.standalone? || description.mongos? || description.primary? || secondary_ok?
128
130
  end
129
131
 
130
132
  def secondary_ok?
@@ -136,16 +138,9 @@ module Mongo
136
138
  log_warn("Rerouting the Aggregation operation to the primary server - #{server.summary} is not suitable")
137
139
  server = cluster.next_primary(nil, session)
138
140
  end
139
- validate_collation!(server)
140
141
  initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
141
142
  end
142
143
 
143
- def validate_collation!(server)
144
- if options[:collation] && !server.with_connection { |connection| connection.features }.collation_enabled?
145
- raise Error::UnsupportedCollation.new
146
- end
147
- end
148
-
149
144
  # Skip, sort, limit, projection are specified as pipeline stages
150
145
  # rather than as options.
151
146
  def cache_options
@@ -79,11 +79,12 @@ module Mongo
79
79
  # @since 2.2.0
80
80
  def specification
81
81
  spec = {
82
- selector: aggregation_command,
83
- db_name: database.name,
84
- read: view.read_preference,
85
- session: @options[:session]
86
- }
82
+ selector: aggregation_command,
83
+ db_name: database.name,
84
+ read: view.read_preference,
85
+ session: @options[:session],
86
+ collation: @options[:collation],
87
+ }
87
88
  if write?
88
89
  spec.update(write_concern: write_concern)
89
90
  end
@@ -36,7 +36,7 @@ module Mongo
36
36
  scope: 'scope',
37
37
  verbose: 'verbose',
38
38
  bypass_document_validation: 'bypassDocumentValidation',
39
- collation: 'collation'
39
+ collation: 'collation',
40
40
  ).freeze
41
41
 
42
42
  def_delegators :@view, :collection, :database, :filter, :read, :write_concern
@@ -71,36 +71,6 @@ module Mongo
71
71
  @options = options
72
72
  end
73
73
 
74
- # Get the specification for issuing a find command on the map/reduce
75
- # results.
76
- #
77
- # @example Get the command specification.
78
- # builder.command_specification
79
- #
80
- # @return [ Hash ] The specification.
81
- #
82
- # @since 2.2.0
83
- def command_specification
84
- {
85
- selector: find_command,
86
- db_name: query_database,
87
- read: read,
88
- session: options[:session]
89
- }
90
- end
91
-
92
- # Get the specification for the document query after a map/reduce.
93
- #
94
- # @example Get the query specification.
95
- # builder.query_specification
96
- #
97
- # @return [ Hash ] The specification.
98
- #
99
- # @since 2.2.0
100
- def query_specification
101
- { selector: {}, options: {}, db_name: query_database, coll_name: query_collection }
102
- end
103
-
104
74
  # Get the specification to pass to the map/reduce operation.
105
75
  #
106
76
  # @example Get the specification.
@@ -113,6 +83,8 @@ module Mongo
113
83
  spec = {
114
84
  selector: map_reduce_command,
115
85
  db_name: database.name,
86
+ # Note that selector just above may also have a read preference
87
+ # specified, per the #map_reduce_command method below.
116
88
  read: read,
117
89
  session: options[:session]
118
90
  }
@@ -121,8 +93,6 @@ module Mongo
121
93
 
122
94
  private
123
95
 
124
- OUT_ACTIONS = [ :replace, :merge, :reduce ].freeze
125
-
126
96
  def write?(spec)
127
97
  if out = spec[:selector][:out]
128
98
  out.is_a?(String) ||
@@ -130,37 +100,30 @@ module Mongo
130
100
  end
131
101
  end
132
102
 
133
- def find_command
134
- BSON::Document.new('find' => query_collection, 'filter' => {})
135
- end
136
-
137
103
  def map_reduce_command
138
104
  command = BSON::Document.new(
139
105
  :mapReduce => collection.name,
140
106
  :map => map,
141
107
  :reduce => reduce,
142
108
  :query => filter,
143
- :out => { inline: 1 }
109
+ :out => { inline: 1 },
144
110
  )
111
+ # Shouldn't this use self.read ?
145
112
  if collection.read_concern
146
113
  command[:readConcern] = Options::Mapper.transform_values_to_strings(
147
114
  collection.read_concern)
148
115
  end
149
- command.merge!(view_options)
116
+ command.update(view_options)
117
+ command.update(Utils.slice_hash(options, :collation))
118
+ # Read preference isn't simply passed in the command payload
119
+ # (it may need to be converted to wire protocol flags)
120
+ # so remove it here and hopefully it's handled elsewhere.
121
+ # If not, RUBY-2706.
122
+ command.delete(:read)
150
123
  command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
151
124
  command
152
125
  end
153
126
 
154
- def query_database
155
- options[:out].respond_to?(:keys) && options[:out][:db] ? options[:out][:db] : database.name
156
- end
157
-
158
- def query_collection
159
- if options[:out].respond_to?(:keys)
160
- options[:out][OUT_ACTIONS.find { |action| options[:out][action] }]
161
- end || options[:out]
162
- end
163
-
164
127
  def view_options
165
128
  @view_options ||= (opts = view.options.dup
166
129
  opts.delete(:session)
@@ -17,7 +17,3 @@
17
17
 
18
18
  require 'mongo/collection/view/builder/aggregation'
19
19
  require 'mongo/collection/view/builder/map_reduce'
20
- require 'mongo/collection/view/builder/op_query'
21
- require 'mongo/collection/view/builder/find_command'
22
- require 'mongo/collection/view/builder/flags'
23
- require 'mongo/collection/view/builder/modifiers'
@@ -25,6 +25,13 @@ module Mongo
25
25
  # @since 2.0.0
26
26
  module Iterable
27
27
 
28
+ # Returns the cursor associated with this view, if any.
29
+ #
30
+ # @return [ nil | Cursor ] The cursor, if any.
31
+ #
32
+ # @api private
33
+ attr_reader :cursor
34
+
28
35
  # Iterate through documents returned by a query with this +View+.
29
36
  #
30
37
  # @example Iterate through the result of the view.
@@ -140,36 +147,53 @@ module Mongo
140
147
  projection: projection,
141
148
  collation: collation,
142
149
  read_concern: read_concern,
143
- read_preference: read_preference
144
-
150
+ read_preference: read_preference,
145
151
  }
146
152
  end
147
153
 
148
154
  def initial_query_op(server, session)
149
- if server.with_connection { |connection| connection.features }.find_command_enabled?
150
- initial_command_op(session)
151
- else
152
- # Server versions that do not have the find command feature
153
- # (versions older than 3.2) do not support the allow_disk_use option
154
- # but perform no validation and will not raise an error if it is
155
- # specified. If the allow_disk_use option is specified, raise an error
156
- # to alert the user.
157
- raise Error::UnsupportedOption.allow_disk_use_error if options.key?(:allow_disk_use)
158
- Operation::Find.new(Builder::OpQuery.new(self).specification)
155
+ spec = {
156
+ coll_name: collection.name,
157
+ filter: filter,
158
+ projection: projection,
159
+ db_name: database.name,
160
+ session: session,
161
+ collation: collation,
162
+ sort: sort,
163
+ skip: skip,
164
+ limit: limit,
165
+ allow_disk_use: options[:allow_disk_use],
166
+ read: read,
167
+ read_concern: options[:read_concern] || read_concern,
168
+ batch_size: batch_size,
169
+ hint: options[:hint],
170
+ max_scan: options[:max_scan],
171
+ max_time_ms: options[:max_time_ms],
172
+ max_value: options[:max_value],
173
+ min_value: options[:min_value],
174
+ return_key: options[:return_key],
175
+ show_disk_loc: options[:show_disk_loc],
176
+ comment: options[:comment],
177
+ oplog_replay: if (v = options[:oplog_replay]).nil?
178
+ collection.options[:oplog_replay]
179
+ else
180
+ v
181
+ end,
182
+ }
183
+
184
+ if spec[:oplog_replay]
185
+ collection.client.log_warn("The :oplog_replay option is deprecated and ignored by MongoDB 4.4 and later")
159
186
  end
160
- end
161
187
 
162
- def initial_command_op(session)
163
- builder = Builder::FindCommand.new(self, session)
164
188
  if explained?
165
- Operation::Explain.new(builder.explain_specification)
189
+ spec[:explain] = options[:explain]
190
+ Operation::Explain.new(spec)
166
191
  else
167
- Operation::Find.new(builder.specification)
192
+ Operation::Find.new(spec)
168
193
  end
169
194
  end
170
195
 
171
196
  def send_initial_query(server, session = nil)
172
- validate_collation!(server, collation)
173
197
  initial_query_op(server, session).execute(server, context: Operation::Context.new(client: client, session: session))
174
198
  end
175
199
 
@@ -156,6 +156,28 @@ module Mongo
156
156
  configure(:out, location)
157
157
  end
158
158
 
159
+ # Returns the collection name where the map-reduce result is written to.
160
+ # If the result is returned inline, returns nil.
161
+ def out_collection_name
162
+ if options[:out].respond_to?(:keys)
163
+ options[:out][OUT_ACTIONS.find do |action|
164
+ options[:out][action]
165
+ end]
166
+ end || options[:out]
167
+ end
168
+
169
+ # Returns the database name where the map-reduce result is written to.
170
+ # If the result is returned inline, returns nil.
171
+ def out_database_name
172
+ if options[:out]
173
+ if options[:out].respond_to?(:keys) && (db = options[:out][:db])
174
+ db
175
+ else
176
+ database.name
177
+ end
178
+ end
179
+ end
180
+
159
181
  # Set or get a scope on the operation.
160
182
  #
161
183
  # @example Set the scope value.
@@ -207,6 +229,8 @@ module Mongo
207
229
 
208
230
  private
209
231
 
232
+ OUT_ACTIONS = [ :replace, :merge, :reduce ].freeze
233
+
210
234
  def server_selector
211
235
  @view.send(:server_selector)
212
236
  end
@@ -228,10 +252,12 @@ module Mongo
228
252
  end
229
253
 
230
254
  def valid_server?(server)
231
- description = server.with_connection do |connection|
232
- connection.description
255
+ if secondary_ok?
256
+ true
257
+ else
258
+ description = server.description
259
+ description.standalone? || description.mongos? || description.primary? || description.load_balancer?
233
260
  end
234
- description.standalone? || description.mongos? || description.primary? || secondary_ok?
235
261
  end
236
262
 
237
263
  def secondary_ok?
@@ -244,7 +270,6 @@ module Mongo
244
270
  log_warn(msg)
245
271
  server = cluster.next_primary(nil, session)
246
272
  end
247
- validate_collation!(server)
248
273
  initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
249
274
  end
250
275
 
@@ -257,22 +282,21 @@ module Mongo
257
282
  end
258
283
 
259
284
  def fetch_query_op(server, session)
260
- if server.with_connection { |connection| connection.features }.find_command_enabled?
261
- Operation::Find.new(find_command_spec(session))
262
- else
263
- Operation::Find.new(fetch_query_spec)
264
- end
285
+ spec = {
286
+ coll_name: out_collection_name,
287
+ db_name: out_database_name,
288
+ filter: {},
289
+ session: session,
290
+ read: read,
291
+ read_concern: options[:read_concern] || collection.read_concern,
292
+ collation: options[:collation] || view.options[:collation],
293
+ }
294
+ Operation::Find.new(spec)
265
295
  end
266
296
 
267
297
  def send_fetch_query(server, session)
268
298
  fetch_query_op(server, session).execute(server, context: Operation::Context.new(client: client, session: session))
269
299
  end
270
-
271
- def validate_collation!(server)
272
- if (view.options[:collation] || options[:collation]) && !server.with_connection { |connection| connection.features }.collation_enabled?
273
- raise Error::UnsupportedCollation.new
274
- end
275
- end
276
300
  end
277
301
  end
278
302
  end