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
@@ -133,7 +133,7 @@ module Mongo
133
133
  end
134
134
  end
135
135
 
136
- sel = selector(connection).dup
136
+ sel = BSON::Document.new(selector(connection))
137
137
  add_write_concern!(sel)
138
138
  sel[Protocol::Msg::DATABASE_IDENTIFIER] = db_name
139
139
 
@@ -169,8 +169,11 @@ module Mongo
169
169
  Lint.assert_type(connection, Server::Connection)
170
170
 
171
171
  # https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#topology-type-single
172
- if connection.description.standalone?
172
+ read_doc = if connection.description.standalone?
173
173
  # Read preference is never sent to standalones.
174
+ nil
175
+ elsif connection.server.load_balancer?
176
+ read&.to_mongos
174
177
  elsif connection.description.mongos?
175
178
  # When server is a mongos:
176
179
  # - $readPreference is never sent when mode is 'primary'
@@ -178,12 +181,7 @@ module Mongo
178
181
  # When mode is 'secondaryPreferred' $readPreference is currently
179
182
  # required to only be sent when a non-mode field (i.e. tag_sets)
180
183
  # is present, but this causes wrong behavior (DRIVERS-1642).
181
- if read
182
- doc = read.to_mongos
183
- if doc
184
- sel['$readPreference'] = doc
185
- end
186
- end
184
+ read&.to_mongos
187
185
  elsif connection.server.cluster.single?
188
186
  # In Single topology:
189
187
  # - If no read preference is specified by the application, the driver
@@ -198,14 +196,21 @@ module Mongo
198
196
  if [nil, 'primary'].include?(read_doc['mode'])
199
197
  read_doc['mode'] = 'primaryPreferred'
200
198
  end
201
- sel['$readPreference'] = read_doc
199
+ read_doc
202
200
  else
203
201
  # In replica sets, read preference is passed to the server if one
204
- # is specified by the application, and there is no default.
205
- if read
206
- sel['$readPreference'] = read.to_doc
202
+ # is specified by the application, except for primary read preferences.
203
+ read_doc = BSON::Document.new(read&.to_doc || {})
204
+ if [nil, 'primary'].include?(read_doc['mode'])
205
+ nil
206
+ else
207
+ read_doc
207
208
  end
208
209
  end
210
+
211
+ if read_doc
212
+ sel['$readPreference'] = read_doc
213
+ end
209
214
  end
210
215
 
211
216
  def apply_session_options(sel, connection)
@@ -224,6 +229,17 @@ module Mongo
224
229
  then
225
230
  sel[:recoveryToken] = session.recovery_token
226
231
  end
232
+
233
+ if session.snapshot?
234
+ unless connection.description.server_version_gte?('5.0')
235
+ raise Error::SnapshotSessionInvalidServerVersion
236
+ end
237
+
238
+ sel[:readConcern] = {level: 'snapshot'}
239
+ if session.snapshot_timestamp
240
+ sel[:readConcern][:atClusterTime] = session.snapshot_timestamp
241
+ end
242
+ end
227
243
  end
228
244
 
229
245
  def build_message(connection, context)
@@ -60,11 +60,6 @@ module Mongo
60
60
  # @since 2.0.0
61
61
  CURSOR_ID = :cursor_id.freeze
62
62
 
63
- # The field for cursor ids.
64
- #
65
- # @since 2.0.0
66
- CURSOR_IDS = :cursor_ids.freeze
67
-
68
63
  # The field for an index.
69
64
  #
70
65
  # @since 2.0.0
@@ -238,7 +233,7 @@ module Mongo
238
233
  #
239
234
  # @since 2.0.0
240
235
  def coll_name
241
- spec[COLL_NAME]
236
+ spec.fetch(COLL_NAME)
242
237
  end
243
238
 
244
239
  # The id of the cursor created on the server.
@@ -253,18 +248,6 @@ module Mongo
253
248
  spec[CURSOR_ID]
254
249
  end
255
250
 
256
- # The ids of the cursors to kill from the spec.
257
- #
258
- # @example Get the cursor ids from the spec.
259
- # specifiable.cursor_ids
260
- #
261
- # @return [ Array<Integer> ] The cursor ids.
262
- #
263
- # @since 2.0.0
264
- def cursor_ids
265
- spec[CURSOR_IDS]
266
- end
267
-
268
251
  # Get the index from the specification.
269
252
  #
270
253
  # @example Get the index specification.
@@ -536,17 +519,6 @@ module Mongo
536
519
  @spec[:txn_num]
537
520
  end
538
521
 
539
- # For createIndexes operations, the number of votes that a primary must
540
- # wait for before commiting an index. Potential values are:
541
- # - an integer from 0 to the number of members of the replica set
542
- # - "majority" indicating that a majority of data bearing nodes must vote
543
- # - "votingMembers" which means that all voting data bearing nodes must vote
544
- #
545
- # @return [ nil | Integer | String ] The commitQuorum value of the operation.
546
- def commit_quorum
547
- @spec[:commit_quorum]
548
- end
549
-
550
522
  # The command.
551
523
  #
552
524
  # @return [ Hash ] The command.
@@ -580,6 +552,16 @@ module Mongo
580
552
  def acknowledged_write?
581
553
  write_concern.nil? || write_concern.acknowledged?
582
554
  end
555
+
556
+ def apply_collation(selector, connection, collation)
557
+ if collation
558
+ unless connection.features.collation_enabled?
559
+ raise Error::UnsupportedCollation
560
+ end
561
+ selector = selector.merge(collation: collation)
562
+ end
563
+ selector
564
+ end
583
565
  end
584
566
  end
585
567
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Mongo
19
+ module Operation
20
+
21
+ # @api private
22
+ module Validatable
23
+
24
+ def validate_find_options(connection, selector)
25
+ if selector.key?(:hint) &&
26
+ !connection.features.find_and_modify_option_validation_enabled?
27
+ then
28
+ raise Error::UnsupportedOption.hint_error
29
+ end
30
+
31
+ if selector.key?(:arrayFilters) &&
32
+ !connection.features.array_filters_enabled?
33
+ then
34
+ raise Error::UnsupportedArrayFilters
35
+ end
36
+
37
+ if selector.key?(:collation) &&
38
+ !connection.features.collation_enabled?
39
+ then
40
+ raise Error::UnsupportedCollation
41
+ end
42
+ end
43
+
44
+ # selector_or_item here is either:
45
+ # - The selector as used in a findAndModify command, or
46
+ # - One of the array elements in the updates array in an update command.
47
+ def validate_hint_on_update(connection, selector_or_item)
48
+ if selector_or_item.key?(:hint) &&
49
+ !connection.features.update_delete_option_validation_enabled?
50
+ then
51
+ raise Error::UnsupportedOption.hint_error
52
+ end
53
+ end
54
+
55
+ # selector_or_item here is either:
56
+ # - The selector as used in a findAndModify command, or
57
+ # - One of the array elements in the updates array in an update command.
58
+ def validate_array_filters(connection, selector_or_item)
59
+ if selector_or_item.key?(:arrayFilters) &&
60
+ !connection.features.array_filters_enabled?
61
+ then
62
+ raise Error::UnsupportedArrayFilters
63
+ end
64
+ end
65
+
66
+ # selector_or_item here is either:
67
+ # - The selector as used in a findAndModify command, or
68
+ # - One of the array elements in the updates array in an update command.
69
+ def validate_collation(connection, selector_or_item)
70
+ if selector_or_item.key?(:collation) &&
71
+ !connection.features.collation_enabled?
72
+ then
73
+ raise Error::UnsupportedCollation
74
+ end
75
+ end
76
+
77
+ def validate_updates(connection, updates)
78
+ updates.each do |update|
79
+ validate_array_filters(connection, update)
80
+ validate_collation(connection, update)
81
+ validate_hint_on_update(connection, update)
82
+ end
83
+ updates
84
+ end
85
+ end
86
+ end
87
+ end
@@ -35,7 +35,7 @@ module Mongo
35
35
  #
36
36
  # @since 2.5.2
37
37
  def execute(server, context:)
38
- server.with_connection do |connection|
38
+ server.with_connection(service_id: context.service_id) do |connection|
39
39
  validate!(connection)
40
40
  op = if connection.features.op_msg_enabled?
41
41
  self.class::OpMsg.new(spec)
@@ -32,13 +32,16 @@ module Mongo
32
32
  include BypassDocumentValidation
33
33
  include ExecutableNoValidate
34
34
  include PolymorphicResult
35
+ include Validatable
35
36
 
36
37
  private
37
38
 
38
39
  def selector(connection)
39
- { update: coll_name,
40
- updates: send(IDENTIFIER),
41
- ordered: ordered? }
40
+ {
41
+ update: coll_name,
42
+ updates: validate_updates(connection, send(IDENTIFIER)),
43
+ ordered: ordered?,
44
+ }
42
45
  end
43
46
 
44
47
  def message(connection)
@@ -30,24 +30,32 @@ module Mongo
30
30
  include Specifiable
31
31
  include Executable
32
32
  include PolymorphicResult
33
+ include Validatable
33
34
 
34
35
  private
35
36
 
36
- def selector
37
- send(IDENTIFIER).first
37
+ def selector(connection)
38
+ # This returns the first update.
39
+ # The driver only puts one update into the list normally, so this
40
+ # doesn't discard operations.
41
+ send(IDENTIFIER).first.tap do |selector|
42
+ validate_find_options(connection, selector)
43
+ end
38
44
  end
39
45
 
40
46
  def message(connection)
47
+ selector = selector(connection)
48
+
41
49
  flags = []
42
50
  flags << :multi_update if selector[Operation::MULTI]
43
51
  flags << :upsert if selector[Operation::UPSERT]
44
52
 
45
53
  Protocol::Update.new(
46
- db_name,
47
- coll_name,
48
- selector[Operation::Q],
49
- selector[Operation::U],
50
- flags.empty? ? {} : { flags: flags }
54
+ db_name,
55
+ coll_name,
56
+ selector[Operation::Q],
57
+ selector[Operation::U],
58
+ flags.empty? ? {} : { flags: flags },
51
59
  )
52
60
  end
53
61
 
@@ -55,10 +63,10 @@ module Mongo
55
63
  wc = write_concern || WriteConcern.get(WriteConcern::DEFAULT)
56
64
  if gle_message = wc.get_last_error
57
65
  Protocol::Query.new(
58
- db_name,
59
- Database::COMMAND,
60
- gle_message,
61
- options.merge(limit: -1)
66
+ db_name,
67
+ Database::COMMAND,
68
+ gle_message,
69
+ options.merge(limit: -1),
62
70
  )
63
71
  end
64
72
  end
@@ -29,17 +29,21 @@ module Mongo
29
29
  include ExecutableNoValidate
30
30
  include ExecutableTransactionLabel
31
31
  include PolymorphicResult
32
+ include Validatable
32
33
 
33
34
  private
34
35
 
35
36
  def selector(connection)
36
- { update: coll_name,
37
- Protocol::Msg::DATABASE_IDENTIFIER => db_name,
38
- ordered: ordered? }
37
+ {
38
+ update: coll_name,
39
+ ordered: ordered?,
40
+ let: spec[:let]
41
+ }.compact
39
42
  end
40
43
 
41
44
  def message(connection)
42
- section = Protocol::Msg::Section1.new(IDENTIFIER, send(IDENTIFIER))
45
+ updates = validate_updates(connection, send(IDENTIFIER))
46
+ section = Protocol::Msg::Section1.new(IDENTIFIER, updates)
43
47
  Protocol::Msg.new(flags, {}, command(connection), section)
44
48
  end
45
49
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Mongo
19
+ module Operation
20
+ class WriteCommand
21
+
22
+ # A MongoDB write command operation sent as a command message.
23
+ #
24
+ # @api private
25
+ class Command
26
+ include Specifiable
27
+ include Executable
28
+ include Limited
29
+ include ReadPreferenceSupported
30
+ include Validatable
31
+
32
+ private
33
+
34
+ def selector(connection)
35
+ super.tap do |selector|
36
+ if selector.key?(:findAndModify)
37
+ validate_find_options(connection, selector)
38
+ end
39
+ if wc = spec[:write_concern]
40
+ selector[:writeConcern] = wc.options
41
+ end
42
+ end
43
+ end
44
+
45
+ def message(connection)
46
+ Protocol::Query.new(db_name, Database::COMMAND, command(connection), options(connection))
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Mongo
19
+ module Operation
20
+ class WriteCommand
21
+
22
+ # A MongoDB write command operation sent as an op message.
23
+ #
24
+ # @api private
25
+ class OpMsg < OpMsgBase
26
+ include Validatable
27
+
28
+ private
29
+
30
+ def selector(connection)
31
+ super.tap do |selector|
32
+ if selector.key?(:findAndModify)
33
+ validate_find_options(connection, selector)
34
+ end
35
+ if wc = spec[:write_concern]
36
+ selector[:writeConcern] = wc.options
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'mongo/operation/write_command/command'
19
+ require 'mongo/operation/write_command/op_msg'
20
+
21
+ module Mongo
22
+ module Operation
23
+
24
+ # A MongoDB general command operation.
25
+ #
26
+ # @api private
27
+ class WriteCommand
28
+ include Specifiable
29
+ include OpMsgOrCommand
30
+ end
31
+ end
32
+ end
@@ -20,12 +20,14 @@ require 'mongo/operation/shared/causal_consistency_supported'
20
20
  require 'mongo/operation/shared/write'
21
21
  require 'mongo/operation/shared/idable'
22
22
  require 'mongo/operation/shared/specifiable'
23
+ require 'mongo/operation/shared/validatable'
23
24
  require 'mongo/operation/shared/object_id_generator'
24
25
  require 'mongo/operation/shared/op_msg_or_command'
25
26
  require 'mongo/operation/shared/op_msg_or_find_command'
26
27
 
27
28
  require 'mongo/operation/op_msg_base'
28
29
  require 'mongo/operation/command'
30
+ require 'mongo/operation/write_command'
29
31
  require 'mongo/operation/aggregate'
30
32
  require 'mongo/operation/result'
31
33
  require 'mongo/operation/collections_info'
@@ -54,6 +56,14 @@ require 'mongo/operation/drop_index'
54
56
 
55
57
  module Mongo
56
58
 
59
+ # This module encapsulates all of the operation classes defined by the driver.
60
+ #
61
+ # The operation classes take Ruby options as constructor parameters.
62
+ # For example, :read contains read preference and :read_concern contains read
63
+ # concern, whereas server commands use readConcern field for the read
64
+ # concern and read preference is passed as $readPreference or secondaryOk
65
+ # wire protocol flag bit.
66
+ #
57
67
  # @api private
58
68
  module Operation
59
69
 
@@ -64,13 +64,21 @@ module Mongo
64
64
  def initialize(database, collection, selector, options = {})
65
65
  @database = database
66
66
  @namespace = "#{database}.#{collection}"
67
+ if selector.nil?
68
+ raise ArgumentError, 'Selector cannot be nil'
69
+ end
67
70
  @selector = selector
68
71
  @options = options
69
72
  @project = options[:project]
70
73
  @limit = determine_limit
71
74
  @skip = options[:skip] || 0
72
75
  @flags = options[:flags] || []
73
- @upconverter = Upconverter.new(collection, selector, options, flags)
76
+ @upconverter = Upconverter.new(
77
+ collection,
78
+ BSON::Document.new(selector),
79
+ BSON::Document.new(options),
80
+ flags,
81
+ )
74
82
  super
75
83
  end
76
84
 
@@ -224,7 +232,7 @@ module Mongo
224
232
  }.freeze
225
233
 
226
234
  SPECIAL_FIELD_MAPPINGS = {
227
- :$readPreference => 'readPreference',
235
+ :$readPreference => '$readPreference',
228
236
  :$orderby => 'sort',
229
237
  :$hint => 'hint',
230
238
  :$comment => 'comment',
@@ -249,16 +257,6 @@ module Mongo
249
257
  :partial => 'allowPartialResults'
250
258
  }.freeze
251
259
 
252
- # Find command constant.
253
- #
254
- # @since 2.1.0
255
- FIND = 'find'.freeze
256
-
257
- # Filter attribute constant.
258
- #
259
- # @since 2.1.0
260
- FILTER = 'filter'.freeze
261
-
262
260
  # @return [ String ] collection The name of the collection.
263
261
  attr_reader :collection
264
262
 
@@ -283,6 +281,15 @@ module Mongo
283
281
  #
284
282
  # @since 2.1.0
285
283
  def initialize(collection, filter, options, flags)
284
+ # Although the docstring claims both hashes and BSON::Documents
285
+ # are acceptable, this class expects the filter and options to
286
+ # contain symbol keys which isn't what the operation layer produces.
287
+ unless BSON::Document === filter
288
+ raise ArgumentError, 'Filter must provide indifferent access'
289
+ end
290
+ unless BSON::Document === options
291
+ raise ArgumentError, 'Options must provide indifferent access'
292
+ end
286
293
  @collection = collection
287
294
  @filter = filter
288
295
  @options = options
@@ -311,7 +318,7 @@ module Mongo
311
318
  #
312
319
  # @since 2.1.0
313
320
  def command_name
314
- ((filter[:$query] || !command?) ? FIND : filter.keys.first).to_s
321
+ ((filter[:$query] || !command?) ? :find : filter.keys.first).to_s
315
322
  end
316
323
 
317
324
  private
@@ -333,15 +340,25 @@ module Mongo
333
340
  end
334
341
 
335
342
  def find_command
336
- document = BSON::Document.new
337
- document.store(FIND, collection)
338
- document.store(FILTER, query_filter)
343
+ document = BSON::Document.new(
344
+ find: collection,
345
+ filter: query_filter,
346
+ )
339
347
  OPTION_MAPPINGS.each do |legacy, option|
340
348
  document.store(option, options[legacy]) unless options[legacy].nil?
341
349
  end
342
- Mongo::Lint.validate_camel_case_read_preference(filter['readPreference'])
350
+ if Lint.enabled?
351
+ filter.each do |k, v|
352
+ unless String === k
353
+ raise Error::LintError, "All keys in filter must be strings: #{filter.inspect}"
354
+ end
355
+ end
356
+ end
357
+ Lint.validate_camel_case_read_preference(filter['readPreference'])
343
358
  SPECIAL_FIELD_MAPPINGS.each do |special, normal|
344
- document.store(normal, filter[special]) unless filter[special].nil?
359
+ unless (v = filter[special]).nil?
360
+ document.store(normal, v)
361
+ end
345
362
  end
346
363
  FLAG_MAPPINGS.each do |legacy, flag|
347
364
  document.store(flag, true) if flags.include?(legacy)
@@ -86,8 +86,12 @@ module Mongo
86
86
  # @param [ Mongo::Server ] server The server the connection is for.
87
87
  # @param [ Hash ] options The connection options.
88
88
  #
89
- # @option options [ Integer ] :generation Connection pool's generation
90
- # for this connection.
89
+ # @option options [ Integer ] :generation The generation of this
90
+ # connection. The generation should only be specified in this option
91
+ # when not in load-balancing mode, and it should be the generation
92
+ # of the connection pool when the connection is created. In
93
+ # load-balancing mode, the generation is set on the connection
94
+ # after the handshake completes.
91
95
  # @option options [ Hash ] :server_api The requested server API version.
92
96
  # This hash can have the following items:
93
97
  # - *:version* -- string
@@ -96,6 +100,10 @@ module Mongo
96
100
  #
97
101
  # @since 2.0.0
98
102
  def initialize(server, options = {})
103
+ if server.load_balancer? && options[:generation]
104
+ raise ArgumentError, "Generation cannot be set when server is a load balancer"
105
+ end
106
+
99
107
  @id = server.next_connection_id
100
108
  @monitoring = server.monitoring
101
109
  @options = options.freeze
@@ -173,6 +181,15 @@ module Mongo
173
181
  # authenticated and be usable.
174
182
  @socket, @description, @compressor = do_connect
175
183
 
184
+ if server.load_balancer?
185
+ if Lint.enabled?
186
+ unless service_id
187
+ raise Error::InternalDriverError, "The connection is to a load balancer and it must have service_id set here, but does not"
188
+ end
189
+ end
190
+ @generation = connection_pool.generation_manager.generation(service_id: service_id)
191
+ end
192
+
176
193
  publish_cmap_event(
177
194
  Monitoring::Event::Cmap::ConnectionReady.new(address, id)
178
195
  )
@@ -314,7 +331,12 @@ module Mongo
314
331
  yield
315
332
  rescue Error::SocketError => e
316
333
  @error = e
317
- @server.unknown!(generation: e.generation, stop_push_monitor: true)
334
+ @server.unknown!(
335
+ generation: e.generation,
336
+ # or description.service_id?
337
+ service_id: e.service_id,
338
+ stop_push_monitor: true,
339
+ )
318
340
  raise
319
341
  rescue Error::SocketTimeoutError => e
320
342
  @error = e