mongo 2.15.1 → 2.16.0.alpha1
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/lib/mongo/bulk_write.rb +2 -2
- data/lib/mongo/client.rb +45 -5
- data/lib/mongo/cluster/periodic_executor.rb +4 -3
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +76 -43
- data/lib/mongo/cluster/sdam_flow.rb +9 -3
- data/lib/mongo/cluster/topology/base.rb +13 -9
- data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
- data/lib/mongo/cluster/topology.rb +28 -8
- data/lib/mongo/cluster.rb +136 -51
- data/lib/mongo/collection/view/aggregation.rb +5 -10
- data/lib/mongo/collection/view/builder/aggregation.rb +6 -5
- data/lib/mongo/collection/view/builder/map_reduce.rb +12 -49
- data/lib/mongo/collection/view/builder.rb +0 -4
- data/lib/mongo/collection/view/iterable.rb +42 -18
- data/lib/mongo/collection/view/map_reduce.rb +39 -15
- data/lib/mongo/collection/view/readable.rb +60 -51
- data/lib/mongo/collection/view/writable.rb +178 -175
- data/lib/mongo/collection/view.rb +15 -21
- data/lib/mongo/collection.rb +13 -13
- data/lib/mongo/cursor/kill_spec.rb +38 -0
- data/lib/mongo/cursor.rb +62 -31
- data/lib/mongo/database/view.rb +1 -1
- data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
- data/lib/mongo/error/missing_service_id.rb +26 -0
- data/lib/mongo/error/no_service_connection_available.rb +49 -0
- data/lib/mongo/error/notable.rb +7 -0
- data/lib/mongo/error.rb +3 -0
- data/lib/mongo/grid/fs_bucket.rb +21 -2
- data/lib/mongo/id.rb +7 -5
- data/lib/mongo/index/view.rb +22 -41
- data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +7 -4
- data/lib/mongo/monitoring/event/command_failed.rb +1 -1
- data/lib/mongo/monitoring/event/command_started.rb +2 -0
- data/lib/mongo/monitoring/publishable.rb +2 -2
- data/lib/mongo/operation/aggregate/command.rb +8 -0
- data/lib/mongo/operation/context.rb +19 -1
- data/lib/mongo/operation/count/command.rb +6 -0
- data/lib/mongo/operation/count/op_msg.rb +6 -0
- data/lib/mongo/operation/create/command.rb +7 -1
- data/lib/mongo/operation/create/op_msg.rb +7 -0
- data/lib/mongo/operation/create_index/command.rb +17 -1
- data/lib/mongo/operation/create_index/op_msg.rb +17 -4
- data/lib/mongo/operation/delete/command.rb +6 -3
- data/lib/mongo/operation/delete/legacy.rb +9 -2
- data/lib/mongo/operation/delete/op_msg.rb +8 -1
- data/lib/mongo/operation/distinct/command.rb +6 -0
- data/lib/mongo/operation/distinct/op_msg.rb +7 -0
- data/lib/mongo/operation/explain/command.rb +13 -1
- data/lib/mongo/operation/explain/legacy.rb +12 -5
- data/lib/mongo/operation/explain/op_msg.rb +9 -1
- data/lib/mongo/operation/find/builder/command.rb +110 -0
- data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +10 -14
- data/lib/mongo/operation/find/builder/legacy.rb +123 -0
- data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +31 -25
- data/lib/mongo/{cursor → operation/find}/builder.rb +4 -4
- data/lib/mongo/operation/find/command.rb +9 -0
- data/lib/mongo/operation/find/legacy.rb +10 -1
- data/lib/mongo/operation/find/op_msg.rb +12 -0
- data/lib/mongo/operation/find.rb +1 -0
- data/lib/mongo/operation/get_more/command.rb +1 -0
- data/lib/mongo/operation/get_more/command_builder.rb +38 -0
- data/lib/mongo/operation/get_more/op_msg.rb +1 -0
- data/lib/mongo/operation/get_more.rb +1 -0
- data/lib/mongo/operation/kill_cursors/command.rb +8 -0
- data/lib/mongo/operation/kill_cursors/command_builder.rb +35 -0
- data/lib/mongo/operation/kill_cursors/legacy.rb +2 -1
- data/lib/mongo/operation/kill_cursors/op_msg.rb +10 -0
- data/lib/mongo/operation/kill_cursors.rb +1 -0
- data/lib/mongo/operation/map_reduce/command.rb +8 -0
- data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
- data/lib/mongo/operation/shared/executable.rb +15 -1
- data/lib/mongo/operation/shared/polymorphic_operation.rb +1 -1
- data/lib/mongo/operation/shared/read_preference_supported.rb +3 -1
- data/lib/mongo/operation/shared/response_handling.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +12 -12
- data/lib/mongo/operation/shared/specifiable.rb +11 -29
- data/lib/mongo/operation/shared/validatable.rb +87 -0
- data/lib/mongo/operation/shared/write.rb +1 -1
- data/lib/mongo/operation/update/command.rb +6 -3
- data/lib/mongo/operation/update/legacy.rb +19 -11
- data/lib/mongo/operation/update/op_msg.rb +7 -4
- data/lib/mongo/operation/write_command/command.rb +51 -0
- data/lib/mongo/operation/write_command/op_msg.rb +43 -0
- data/lib/mongo/operation/write_command.rb +32 -0
- data/lib/mongo/operation.rb +10 -0
- data/lib/mongo/protocol/query.rb +35 -18
- data/lib/mongo/server/connection.rb +25 -3
- data/lib/mongo/server/connection_base.rb +12 -1
- data/lib/mongo/server/connection_common.rb +38 -1
- data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
- data/lib/mongo/server/connection_pool.rb +100 -27
- data/lib/mongo/server/description/features.rb +17 -16
- data/lib/mongo/server/description/load_balancer.rb +33 -0
- data/lib/mongo/server/description.rb +85 -6
- data/lib/mongo/server/monitor/connection.rb +5 -6
- data/lib/mongo/server/monitor.rb +2 -1
- data/lib/mongo/server/pending_connection.rb +47 -31
- data/lib/mongo/server.rb +73 -26
- data/lib/mongo/server_selector/base.rb +5 -1
- data/lib/mongo/session/session_pool.rb +11 -0
- data/lib/mongo/session.rb +21 -1
- data/lib/mongo/socket/ocsp_verifier.rb +6 -37
- data/lib/mongo/uri/options_mapper.rb +1 -0
- data/lib/mongo/uri/srv_protocol.rb +6 -8
- data/lib/mongo/uri.rb +18 -0
- data/lib/mongo/utils.rb +0 -7
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/integration/auth_spec.rb +31 -1
- data/spec/integration/awaited_ismaster_spec.rb +1 -1
- data/spec/integration/bulk_write_spec.rb +1 -1
- data/spec/integration/change_stream_spec.rb +3 -3
- data/spec/integration/client_construction_spec.rb +54 -0
- data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +1 -1
- data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +1 -1
- data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +1 -1
- data/spec/integration/client_side_encryption/data_key_spec.rb +1 -1
- data/spec/integration/client_spec.rb +2 -0
- data/spec/integration/command_monitoring_spec.rb +1 -1
- data/spec/integration/command_spec.rb +1 -1
- data/spec/integration/connection_spec.rb +52 -35
- data/spec/integration/crud_spec.rb +174 -1
- data/spec/integration/cursor_pinning_spec.rb +121 -0
- data/spec/integration/cursor_reaping_spec.rb +8 -4
- data/spec/integration/fork_reconnect_spec.rb +1 -5
- data/spec/integration/get_more_spec.rb +1 -1
- data/spec/integration/heartbeat_events_spec.rb +1 -1
- data/spec/integration/map_reduce_spec.rb +77 -0
- data/spec/integration/query_cache_spec.rb +2 -2
- data/spec/integration/query_cache_transactions_spec.rb +1 -1
- data/spec/integration/read_concern_spec.rb +1 -1
- data/spec/integration/read_preference_spec.rb +1 -1
- data/spec/integration/reconnect_spec.rb +30 -12
- data/spec/integration/retryable_errors_spec.rb +1 -1
- data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
- data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -1
- data/spec/integration/sdam_error_handling_spec.rb +5 -3
- data/spec/integration/sdam_events_spec.rb +35 -19
- data/spec/integration/sdam_prose_spec.rb +1 -1
- data/spec/integration/server_monitor_spec.rb +1 -0
- data/spec/integration/server_selector_spec.rb +22 -5
- data/spec/integration/server_spec.rb +2 -0
- data/spec/integration/srv_monitoring_spec.rb +1 -1
- data/spec/integration/step_down_spec.rb +1 -1
- data/spec/integration/transaction_pinning_spec.rb +120 -0
- data/spec/integration/versioned_api_examples_spec.rb +45 -0
- data/spec/integration/x509_auth_spec.rb +1 -1
- data/spec/lite_spec_helper.rb +1 -2
- data/spec/mongo/address/unix_spec.rb +1 -0
- data/spec/mongo/auth/cr_spec.rb +2 -3
- data/spec/mongo/auth/ldap_spec.rb +2 -3
- data/spec/mongo/auth/scram_spec.rb +2 -3
- data/spec/mongo/auth/user/view_spec.rb +1 -1
- data/spec/mongo/auth/x509_spec.rb +2 -3
- data/spec/mongo/bulk_write_spec.rb +3 -3
- data/spec/mongo/client_construction_spec.rb +259 -28
- data/spec/mongo/client_spec.rb +6 -4
- data/spec/mongo/cluster/cursor_reaper_spec.rb +36 -21
- data/spec/mongo/cluster/periodic_executor_spec.rb +3 -1
- data/spec/mongo/cluster_spec.rb +44 -3
- data/spec/mongo/collection/view/aggregation_spec.rb +1 -1
- data/spec/mongo/collection/view/builder/find_command_spec.rb +4 -0
- data/spec/mongo/collection/view/builder/op_query_spec.rb +4 -0
- data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
- data/spec/mongo/collection_crud_spec.rb +7 -2
- data/spec/mongo/collection_ddl_spec.rb +1 -1
- data/spec/mongo/collection_spec.rb +1 -1
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -0
- data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -0
- data/spec/mongo/cursor_spec.rb +15 -5
- data/spec/mongo/database_spec.rb +15 -15
- data/spec/mongo/error/operation_failure_heavy_spec.rb +1 -1
- data/spec/mongo/grid/fs_bucket_spec.rb +18 -12
- data/spec/mongo/grid/stream/write_spec.rb +3 -9
- data/spec/mongo/grid/stream_spec.rb +1 -1
- data/spec/mongo/index/view_spec.rb +2 -2
- data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
- data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +2 -2
- data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +2 -2
- data/spec/mongo/operation/find/legacy_spec.rb +1 -0
- data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
- data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
- data/spec/mongo/operation/kill_cursors_spec.rb +4 -1
- data/spec/mongo/operation/read_preference_legacy_spec.rb +4 -0
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +2 -0
- data/spec/mongo/operation/update/bulk_spec.rb +1 -1
- data/spec/mongo/operation/update/op_msg_spec.rb +1 -1
- data/spec/mongo/query_cache_spec.rb +6 -2
- data/spec/mongo/server/connection_common_spec.rb +62 -11
- data/spec/mongo/server/connection_pool_spec.rb +73 -7
- data/spec/mongo/server/connection_spec.rb +138 -43
- data/spec/mongo/server/description_spec.rb +1 -1
- data/spec/mongo/server/monitor_spec.rb +4 -3
- data/spec/mongo/session/session_pool_spec.rb +42 -10
- data/spec/mongo/session_transaction_spec.rb +15 -30
- data/spec/mongo/socket/unix_spec.rb +1 -0
- data/spec/mongo/uri_option_parsing_spec.rb +38 -5
- data/spec/runners/change_streams/test.rb +1 -1
- data/spec/runners/cmap.rb +1 -1
- data/spec/runners/connection_string.rb +7 -3
- data/spec/runners/crud/operation.rb +5 -3
- data/spec/runners/crud/requirement.rb +1 -0
- data/spec/runners/crud.rb +1 -1
- data/spec/runners/sdam.rb +2 -1
- data/spec/runners/transactions/test.rb +2 -2
- data/spec/runners/unified/assertions.rb +2 -3
- data/spec/runners/unified/event_subscriber.rb +2 -2
- data/spec/runners/unified/test.rb +3 -0
- data/spec/runners/unified.rb +1 -1
- data/spec/shared/lib/mrss/constraints.rb +11 -5
- data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
- data/spec/shared/share/Dockerfile.erb +2 -1
- data/spec/shared/shlib/server.sh +70 -20
- data/spec/spec_tests/change_streams_spec.rb +1 -1
- data/spec/spec_tests/cmap_spec.rb +4 -1
- data/spec/spec_tests/command_monitoring_spec.rb +2 -2
- data/spec/spec_tests/data/command_monitoring/find.yml +9 -9
- data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
- data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
- data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
- data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
- data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
- data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
- data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
- data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
- data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
- data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
- data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
- data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
- data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
- data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
- data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
- data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
- data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
- data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +1 -1
- data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +1 -1
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +1 -1
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
- data/spec/spec_tests/data/retryable_reads/mapReduce.yml +3 -1
- data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
- data/spec/spec_tests/data/sdam_integration/find-network-error.yml +2 -0
- data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +2 -0
- data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +3 -1
- data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +3 -1
- data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +2 -0
- data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +2 -0
- data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +2 -0
- data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
- data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
- data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
- data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
- data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-false.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/direct-connection-true.yml +0 -0
- data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
- data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
- data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
- data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
- data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
- data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +2 -0
- data/spec/spec_tests/data/transactions/retryable-abort.yml +2 -0
- data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +2 -0
- data/spec/spec_tests/data/transactions/retryable-commit.yml +2 -0
- data/spec/spec_tests/data/transactions/retryable-writes.yml +2 -0
- data/spec/spec_tests/data/uri_options/connection-options.yml +60 -0
- data/spec/spec_tests/load_balancers_spec.rb +15 -0
- data/spec/spec_tests/retryable_reads_spec.rb +2 -2
- data/spec/spec_tests/retryable_writes_spec.rb +1 -1
- data/spec/spec_tests/sdam_integration_spec.rb +1 -1
- data/spec/spec_tests/sdam_monitoring_spec.rb +10 -5
- data/spec/spec_tests/sdam_spec.rb +1 -1
- data/spec/spec_tests/seed_list_discovery_spec.rb +118 -0
- data/spec/spec_tests/uri_options_spec.rb +4 -4
- data/spec/stress/fork_reconnect_stress_spec.rb +1 -5
- data/spec/support/certificates/atlas-ocsp-ca.crt +82 -90
- data/spec/support/certificates/atlas-ocsp.crt +127 -122
- data/spec/support/common_shortcuts.rb +2 -3
- data/spec/support/matchers.rb +13 -0
- data/spec/support/shared/auth_context.rb +16 -0
- data/spec/support/shared/session.rb +2 -2
- data/spec/support/spec_config.rb +9 -10
- data/spec/support/using_hash.rb +31 -0
- data/spec/support/utils.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +120 -76
- metadata.gz.sig +0 -0
- data/lib/mongo/collection/view/builder/find_command.rb +0 -173
- data/lib/mongo/collection/view/builder/op_query.rb +0 -94
- data/lib/mongo/cursor/builder/get_more_command.rb +0 -80
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -111
- data/lib/mongo/cursor/builder/op_get_more.rb +0 -64
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -106
- data/lib/mongo/server/context.rb +0 -72
- data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -66
- data/spec/runners/unified/using_hash.rb +0 -34
- data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -79
- data/spec/support/event_subscriber.rb +0 -221
| @@ -14,7 +14,6 @@ | |
| 14 14 | 
             
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 15 15 | 
             
            # See the License for the specific language governing permissions and
         | 
| 16 16 | 
             
            # limitations under the License.
         | 
| 17 | 
            -
            require 'mongo/server/connection_pool/populator'
         | 
| 18 17 |  | 
| 19 18 | 
             
            module Mongo
         | 
| 20 19 | 
             
              class Server
         | 
| @@ -111,7 +110,7 @@ module Mongo | |
| 111 110 | 
             
                    @server = server
         | 
| 112 111 | 
             
                    @options = options.freeze
         | 
| 113 112 |  | 
| 114 | 
            -
                    @ | 
| 113 | 
            +
                    @generation_manager = GenerationManager.new(server: server)
         | 
| 115 114 | 
             
                    @closed = false
         | 
| 116 115 |  | 
| 117 116 | 
             
                    # A connection owned by this pool should be either in the
         | 
| @@ -189,12 +188,14 @@ module Mongo | |
| 189 188 | 
             
                    @max_idle_time ||= options[:max_idle_time]
         | 
| 190 189 | 
             
                  end
         | 
| 191 190 |  | 
| 191 | 
            +
                  # @api private
         | 
| 192 | 
            +
                  attr_reader :generation_manager
         | 
| 193 | 
            +
             | 
| 192 194 | 
             
                  # @return [ Integer ] generation Generation of connections currently
         | 
| 193 195 | 
             
                  #   being used by the queue.
         | 
| 194 196 | 
             
                  #
         | 
| 195 | 
            -
                  # @since 2.9.0
         | 
| 196 197 | 
             
                  # @api private
         | 
| 197 | 
            -
                   | 
| 198 | 
            +
                  def_delegator :generation_manager, :generation
         | 
| 198 199 |  | 
| 199 200 | 
             
                  # Size of the connection pool.
         | 
| 200 201 | 
             
                  #
         | 
| @@ -277,7 +278,7 @@ module Mongo | |
| 277 278 | 
             
                  #   and remains so for longer than the wait timeout.
         | 
| 278 279 | 
             
                  #
         | 
| 279 280 | 
             
                  # @since 2.9.0
         | 
| 280 | 
            -
                  def check_out
         | 
| 281 | 
            +
                  def check_out(service_id: nil)
         | 
| 281 282 | 
             
                    check_invariants
         | 
| 282 283 |  | 
| 283 284 | 
             
                    publish_cmap_event(
         | 
| @@ -306,7 +307,12 @@ module Mongo | |
| 306 307 | 
             
                        # a connection while this thread is waiting for one.
         | 
| 307 308 | 
             
                        @lock.synchronize do
         | 
| 308 309 | 
             
                          until @available_connections.empty?
         | 
| 309 | 
            -
                            connection =  | 
| 310 | 
            +
                            connection = next_available_connection(service_id: service_id)
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                            # If service_id is not nil, connection may be nil here
         | 
| 313 | 
            +
                            # even if there are available connections in the pool
         | 
| 314 | 
            +
                            # (they could be to other services).
         | 
| 315 | 
            +
                            break unless connection
         | 
| 310 316 |  | 
| 311 317 | 
             
                            if connection.pid != pid
         | 
| 312 318 | 
             
                              log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{connection.pid}, new pid #{pid}")
         | 
| @@ -315,7 +321,7 @@ module Mongo | |
| 315 321 | 
             
                              next
         | 
| 316 322 | 
             
                            end
         | 
| 317 323 |  | 
| 318 | 
            -
                            if connection.generation != generation
         | 
| 324 | 
            +
                            if connection.generation != generation(service_id: connection.service_id)
         | 
| 319 325 | 
             
                              # Stale connections should be disconnected in the clear
         | 
| 320 326 | 
             
                              # method, but if any don't, check again here
         | 
| 321 327 | 
             
                              connection.disconnect!(reason: :stale)
         | 
| @@ -335,12 +341,22 @@ module Mongo | |
| 335 341 | 
             
                            throw(:done)
         | 
| 336 342 | 
             
                          end
         | 
| 337 343 |  | 
| 338 | 
            -
                           | 
| 339 | 
            -
             | 
| 340 | 
            -
             | 
| 341 | 
            -
                             | 
| 342 | 
            -
                             | 
| 343 | 
            -
                             | 
| 344 | 
            +
                          if service_id
         | 
| 345 | 
            +
                            # If we need a connection to a particular service, we can't
         | 
| 346 | 
            +
                            # create one if we don't already have one, but we can wait
         | 
| 347 | 
            +
                            # for an in-progress operation to return such a connection
         | 
| 348 | 
            +
                            # to the pool, or for the populator to create a suitable
         | 
| 349 | 
            +
                            # connection.
         | 
| 350 | 
            +
                          else
         | 
| 351 | 
            +
                            # If we are below pool capacity, create a new connection.
         | 
| 352 | 
            +
                            #
         | 
| 353 | 
            +
                            # Ruby does not allow a thread to lock a mutex which it already
         | 
| 354 | 
            +
                            # holds.
         | 
| 355 | 
            +
                            if unsynchronized_size < max_size
         | 
| 356 | 
            +
                              connection = create_connection
         | 
| 357 | 
            +
                              @pending_connections << connection
         | 
| 358 | 
            +
                              throw(:done)
         | 
| 359 | 
            +
                            end
         | 
| 344 360 | 
             
                          end
         | 
| 345 361 | 
             
                        end
         | 
| 346 362 |  | 
| @@ -354,8 +370,14 @@ module Mongo | |
| 354 370 | 
             
                          )
         | 
| 355 371 |  | 
| 356 372 | 
             
                          msg = @lock.synchronize do
         | 
| 373 | 
            +
                            service_id_msg = if service_id
         | 
| 374 | 
            +
                              " for service #{service_id}"
         | 
| 375 | 
            +
                            else
         | 
| 376 | 
            +
                              ''
         | 
| 377 | 
            +
                            end
         | 
| 378 | 
            +
             | 
| 357 379 | 
             
                            "Timed out attempting to check out a connection " +
         | 
| 358 | 
            -
                              "from pool for #{@server.address} after #{wait_timeout} sec. " +
         | 
| 380 | 
            +
                              "from pool for #{@server.address}#{service_id_msg} after #{wait_timeout} sec. " +
         | 
| 359 381 | 
             
                              "Connections in pool: #{@available_connections.length} available, " +
         | 
| 360 382 | 
             
                              "#{@checked_out_connections.length} checked out, " +
         | 
| 361 383 | 
             
                              "#{@pending_connections.length} pending " +
         | 
| @@ -449,7 +471,7 @@ module Mongo | |
| 449 471 | 
             
                        # Connection was closed - for example, because it experienced
         | 
| 450 472 | 
             
                        # a network error. Nothing else needs to be done here.
         | 
| 451 473 | 
             
                        @populate_semaphore.signal
         | 
| 452 | 
            -
                      elsif connection.generation !=  | 
| 474 | 
            +
                      elsif connection.generation != generation(service_id: connection.service_id)
         | 
| 453 475 | 
             
                        connection.disconnect!(reason: :stale)
         | 
| 454 476 | 
             
                        @populate_semaphore.signal
         | 
| 455 477 | 
             
                      else
         | 
| @@ -473,8 +495,12 @@ module Mongo | |
| 473 495 | 
             
                  # @option options [ true | false ] :lazy If true, do not close any of
         | 
| 474 496 | 
             
                  #   the idle connections and instead let them be closed during a
         | 
| 475 497 | 
             
                  #   subsequent check out operation.
         | 
| 498 | 
            +
                  # @option options [ Object ] :service_id Discard state for the specified
         | 
| 499 | 
            +
                  #   service id only.
         | 
| 476 500 | 
             
                  # @option options [ true | false ] :stop_populator Whether to stop
         | 
| 477 501 | 
             
                  #   the populator background thread. For internal driver use only.
         | 
| 502 | 
            +
                  # @option options [ Object ] :service_id Clear connections with
         | 
| 503 | 
            +
                  #   the specified service id only.
         | 
| 478 504 | 
             
                  #
         | 
| 479 505 | 
             
                  # @return [ true ] true.
         | 
| 480 506 | 
             
                  #
         | 
| @@ -488,18 +514,38 @@ module Mongo | |
| 488 514 | 
             
                      stop_populator
         | 
| 489 515 | 
             
                    end
         | 
| 490 516 |  | 
| 517 | 
            +
                    service_id = options && options[:service_id]
         | 
| 518 | 
            +
             | 
| 491 519 | 
             
                    @lock.synchronize do
         | 
| 492 | 
            -
                      @ | 
| 520 | 
            +
                      @generation_manager.bump(service_id: service_id)
         | 
| 493 521 |  | 
| 494 522 | 
             
                      publish_cmap_event(
         | 
| 495 | 
            -
                        Monitoring::Event::Cmap::PoolCleared.new( | 
| 523 | 
            +
                        Monitoring::Event::Cmap::PoolCleared.new(
         | 
| 524 | 
            +
                          @server.address,
         | 
| 525 | 
            +
                          service_id: service_id,
         | 
| 526 | 
            +
                        )
         | 
| 496 527 | 
             
                      )
         | 
| 497 528 |  | 
| 498 529 | 
             
                      unless options && options[:lazy]
         | 
| 499 | 
            -
                         | 
| 500 | 
            -
                           | 
| 501 | 
            -
             | 
| 502 | 
            -
             | 
| 530 | 
            +
                        if service_id
         | 
| 531 | 
            +
                          loop do
         | 
| 532 | 
            +
                            conn = @available_connections.detect do |conn|
         | 
| 533 | 
            +
                              conn.service_id == service_id
         | 
| 534 | 
            +
                            end
         | 
| 535 | 
            +
                            if conn
         | 
| 536 | 
            +
                              @available_connections.delete(conn)
         | 
| 537 | 
            +
                              conn.disconnect!(reason: :stale)
         | 
| 538 | 
            +
                              @populate_semaphore.signal
         | 
| 539 | 
            +
                            else
         | 
| 540 | 
            +
                              break
         | 
| 541 | 
            +
                            end
         | 
| 542 | 
            +
                          end
         | 
| 543 | 
            +
                        else
         | 
| 544 | 
            +
                          until @available_connections.empty?
         | 
| 545 | 
            +
                            connection = @available_connections.pop
         | 
| 546 | 
            +
                            connection.disconnect!(reason: :stale)
         | 
| 547 | 
            +
                            @populate_semaphore.signal
         | 
| 548 | 
            +
                          end
         | 
| 503 549 | 
             
                        end
         | 
| 504 550 | 
             
                      end
         | 
| 505 551 | 
             
                    end
         | 
| @@ -586,10 +632,10 @@ module Mongo | |
| 586 632 | 
             
                  # @return [ Object ] The result of the block.
         | 
| 587 633 | 
             
                  #
         | 
| 588 634 | 
             
                  # @since 2.0.0
         | 
| 589 | 
            -
                  def with_connection
         | 
| 635 | 
            +
                  def with_connection(service_id: nil)
         | 
| 590 636 | 
             
                    raise_if_closed!
         | 
| 591 637 |  | 
| 592 | 
            -
                    connection = check_out
         | 
| 638 | 
            +
                    connection = check_out(service_id: service_id)
         | 
| 593 639 | 
             
                    yield(connection)
         | 
| 594 640 | 
             
                  ensure
         | 
| 595 641 | 
             
                    if connection
         | 
| @@ -705,13 +751,33 @@ module Mongo | |
| 705 751 |  | 
| 706 752 | 
             
                  private
         | 
| 707 753 |  | 
| 754 | 
            +
                  # Returns the next available connection, optionally scoped to the
         | 
| 755 | 
            +
                  # specified service. If no suitable connections are available,
         | 
| 756 | 
            +
                  # returns nil.
         | 
| 757 | 
            +
                  def next_available_connection(service_id: nil)
         | 
| 758 | 
            +
                    if service_id
         | 
| 759 | 
            +
                      conn = @available_connections.detect do |conn|
         | 
| 760 | 
            +
                        conn.service_id == service_id
         | 
| 761 | 
            +
                      end
         | 
| 762 | 
            +
                      if conn
         | 
| 763 | 
            +
                        @available_connections.delete(conn)
         | 
| 764 | 
            +
                      end
         | 
| 765 | 
            +
                      conn
         | 
| 766 | 
            +
                    else
         | 
| 767 | 
            +
                      @available_connections.pop
         | 
| 768 | 
            +
                    end
         | 
| 769 | 
            +
                  end
         | 
| 770 | 
            +
             | 
| 708 771 | 
             
                  def create_connection
         | 
| 709 | 
            -
                     | 
| 710 | 
            -
                      generation: generation,
         | 
| 772 | 
            +
                    opts = options.merge(
         | 
| 711 773 | 
             
                      connection_pool: self,
         | 
| 712 774 | 
             
                      # Do not pass app metadata - this will be retrieved by the connection
         | 
| 713 775 | 
             
                      # based on the auth needs.
         | 
| 714 | 
            -
                    ) | 
| 776 | 
            +
                    )
         | 
| 777 | 
            +
                    unless @server.load_balancer?
         | 
| 778 | 
            +
                      opts[:generation] = generation
         | 
| 779 | 
            +
                    end
         | 
| 780 | 
            +
                    connection = Connection.new(@server, opts)
         | 
| 715 781 | 
             
                  end
         | 
| 716 782 |  | 
| 717 783 | 
             
                  # Create a connection, connect it, and add it to the pool.
         | 
| @@ -772,7 +838,11 @@ module Mongo | |
| 772 838 | 
             
                      raise
         | 
| 773 839 | 
             
                    end
         | 
| 774 840 | 
             
                  rescue Error::SocketError, Error::SocketTimeoutError => exc
         | 
| 775 | 
            -
                    @server.unknown!( | 
| 841 | 
            +
                    @server.unknown!(
         | 
| 842 | 
            +
                      generation: exc.generation,
         | 
| 843 | 
            +
                      service_id: exc.service_id,
         | 
| 844 | 
            +
                      stop_push_monitor: true,
         | 
| 845 | 
            +
                    )
         | 
| 776 846 | 
             
                    raise
         | 
| 777 847 | 
             
                  end
         | 
| 778 848 |  | 
| @@ -800,3 +870,6 @@ module Mongo | |
| 800 870 | 
             
                end
         | 
| 801 871 | 
             
              end
         | 
| 802 872 | 
             
            end
         | 
| 873 | 
            +
             | 
| 874 | 
            +
            require 'mongo/server/connection_pool/generation_manager'
         | 
| 875 | 
            +
            require 'mongo/server/connection_pool/populator'
         | 
| @@ -38,28 +38,29 @@ module Mongo | |
| 38 38 | 
             
                    #
         | 
| 39 39 | 
             
                    # @since 2.0.0
         | 
| 40 40 | 
             
                    MAPPINGS = {
         | 
| 41 | 
            -
                      : | 
| 41 | 
            +
                      retryable_write_error_label: 9,
         | 
| 42 | 
            +
                      commit_quorum: 9,
         | 
| 42 43 | 
             
                      # Server versions older than 4.2 do not reliably validate options
         | 
| 43 44 | 
             
                      # provided by the client during findAndModify operations, requiring the
         | 
| 44 45 | 
             
                      # driver to raise client-side errors when those options are provided.
         | 
| 45 | 
            -
                      : | 
| 46 | 
            -
                      : | 
| 47 | 
            -
                      : | 
| 48 | 
            -
                      : | 
| 49 | 
            -
                      : | 
| 50 | 
            -
                      : | 
| 51 | 
            -
                      : | 
| 52 | 
            -
                      : | 
| 46 | 
            +
                      find_and_modify_option_validation: 8,
         | 
| 47 | 
            +
                      transactions: 7,
         | 
| 48 | 
            +
                      scram_sha_256: 7,
         | 
| 49 | 
            +
                      array_filters: 6,
         | 
| 50 | 
            +
                      op_msg: 6,
         | 
| 51 | 
            +
                      sessions: 6,
         | 
| 52 | 
            +
                      collation: 5,
         | 
| 53 | 
            +
                      max_staleness: 5,
         | 
| 53 54 | 
             
                      # Server versions older than 3.4 do not reliably validate options
         | 
| 54 55 | 
             
                      # provided by the client during update/delete operations, requiring the
         | 
| 55 56 | 
             
                      # driver to raise client-side errors when those options are provided.
         | 
| 56 | 
            -
                      : | 
| 57 | 
            -
                      : | 
| 58 | 
            -
                      : | 
| 59 | 
            -
                      : | 
| 60 | 
            -
                      : | 
| 61 | 
            -
                      : | 
| 62 | 
            -
                      : | 
| 57 | 
            +
                      update_delete_option_validation: 5,
         | 
| 58 | 
            +
                      find_command: 4,
         | 
| 59 | 
            +
                      list_collections: 3,
         | 
| 60 | 
            +
                      list_indexes: 3,
         | 
| 61 | 
            +
                      scram_sha_1: 3,
         | 
| 62 | 
            +
                      write_command: 2,
         | 
| 63 | 
            +
                      users_info: 2,
         | 
| 63 64 | 
             
                    }.freeze
         | 
| 64 65 |  | 
| 65 66 | 
             
                    # Error message if the server is too old for this version of the driver.
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            # encoding: utf-8
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            # Copyright (C) 2021 MongoDB Inc.
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            # Licensed under the Apache License, Version 2.0 (the 'License');
         | 
| 7 | 
            +
            # you may not use this file except in compliance with the License.
         | 
| 8 | 
            +
            # You may obtain a copy of the License at
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         | 
| 11 | 
            +
            #
         | 
| 12 | 
            +
            # Unless required by applicable law or agreed to in writing, software
         | 
| 13 | 
            +
            # distributed under the License is distributed on an 'AS IS' BASIS,
         | 
| 14 | 
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 15 | 
            +
            # See the License for the specific language governing permissions and
         | 
| 16 | 
            +
            # limitations under the License.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            module Mongo
         | 
| 19 | 
            +
              class Server
         | 
| 20 | 
            +
                class Description
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # Represents an assumed description of servers behind load balancers.
         | 
| 23 | 
            +
                  class LoadBalancer
         | 
| 24 | 
            +
                    def initialize(address)
         | 
| 25 | 
            +
                      @address = address
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    # @return [ Address ] address The server's address.
         | 
| 29 | 
            +
                    attr_reader :address
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -15,8 +15,6 @@ | |
| 15 15 | 
             
            # See the License for the specific language governing permissions and
         | 
| 16 16 | 
             
            # limitations under the License.
         | 
| 17 17 |  | 
| 18 | 
            -
            require 'mongo/server/description/features'
         | 
| 19 | 
            -
             | 
| 20 18 | 
             
            module Mongo
         | 
| 21 19 | 
             
              class Server
         | 
| 22 20 |  | 
| @@ -201,7 +199,8 @@ module Mongo | |
| 201 199 | 
             
                                           ].freeze
         | 
| 202 200 |  | 
| 203 201 | 
             
                  # Instantiate the new server description from the result of the hello
         | 
| 204 | 
            -
                  # command | 
| 202 | 
            +
                  # command or fabricate a placeholder description for Unknown and
         | 
| 203 | 
            +
                  # LoadBalancer servers.
         | 
| 205 204 | 
             
                  #
         | 
| 206 205 | 
             
                  # @example Instantiate the new description.
         | 
| 207 206 | 
             
                  #   Description.new(address, { 'isWritablePrimary' => true }, 0.5)
         | 
| @@ -209,17 +208,67 @@ module Mongo | |
| 209 208 | 
             
                  # @param [ Address ] address The server address.
         | 
| 210 209 | 
             
                  # @param [ Hash ] config The result of the hello command.
         | 
| 211 210 | 
             
                  # @param [ Float ] average_round_trip_time The moving average time (sec) the hello
         | 
| 212 | 
            -
                  #    | 
| 211 | 
            +
                  #   command took to complete.
         | 
| 212 | 
            +
                  # @param [ Float ] average_round_trip_time The moving average time (sec)
         | 
| 213 | 
            +
                  #   the ismaster call took to complete.
         | 
| 214 | 
            +
                  # @param [ true | false ] load_balancer Whether the server is treated as
         | 
| 215 | 
            +
                  #   a load balancer.
         | 
| 216 | 
            +
                  # @param [ true | false ] force_load_balancer Whether the server is
         | 
| 217 | 
            +
                  #   forced to be a load balancer.
         | 
| 213 218 | 
             
                  #
         | 
| 214 | 
            -
                  # @ | 
| 215 | 
            -
                  def initialize(address, config = {}, average_round_trip_time  | 
| 219 | 
            +
                  # @api private
         | 
| 220 | 
            +
                  def initialize(address, config = {}, average_round_trip_time: nil,
         | 
| 221 | 
            +
                    load_balancer: false, force_load_balancer: false
         | 
| 222 | 
            +
                  )
         | 
| 216 223 | 
             
                    @address = address
         | 
| 217 224 | 
             
                    @config = config
         | 
| 225 | 
            +
                    @load_balancer = !!load_balancer
         | 
| 226 | 
            +
                    @force_load_balancer = !!force_load_balancer
         | 
| 218 227 | 
             
                    @features = Features.new(wire_versions, me || @address.to_s)
         | 
| 219 228 | 
             
                    @average_round_trip_time = average_round_trip_time
         | 
| 220 229 | 
             
                    @last_update_time = Time.now.freeze
         | 
| 221 230 | 
             
                    @last_update_monotime = Utils.monotonic_time
         | 
| 222 231 |  | 
| 232 | 
            +
                    if load_balancer
         | 
| 233 | 
            +
                      # When loadBalanced=true URI option is set, the driver will refuse
         | 
| 234 | 
            +
                      # to work if the server it communicates with does not set serviceId
         | 
| 235 | 
            +
                      # in ismaster/hello response.
         | 
| 236 | 
            +
                      #
         | 
| 237 | 
            +
                      # In practice, there are currently no server version that actually
         | 
| 238 | 
            +
                      # sets this field.
         | 
| 239 | 
            +
                      #
         | 
| 240 | 
            +
                      # Therefore, when connect=:load_balanced Ruby option is used instead
         | 
| 241 | 
            +
                      # of the loadBalanced=true URI option, if serviceId is not set in
         | 
| 242 | 
            +
                      # ismaster/hello response, the driver fabricates a serviceId and
         | 
| 243 | 
            +
                      # proceeds to treat a server that does not report itself as being
         | 
| 244 | 
            +
                      # behind a load balancer as a server that is behind a load balancer.
         | 
| 245 | 
            +
                      #
         | 
| 246 | 
            +
                      # 5.0+ servers should provide topologyVersion.processId which
         | 
| 247 | 
            +
                      # is specific to the particular process instance. We can use that
         | 
| 248 | 
            +
                      # field as a proxy for serviceId.
         | 
| 249 | 
            +
                      #
         | 
| 250 | 
            +
                      # If the topologyVersion isn't provided for whatever reason, we
         | 
| 251 | 
            +
                      # fabricate a serviceId locally.
         | 
| 252 | 
            +
                      #
         | 
| 253 | 
            +
                      # In either case, a serviceId provided by an actual server behind
         | 
| 254 | 
            +
                      # a load balancer is supposed to be a BSON::ObjectId. The fabricated
         | 
| 255 | 
            +
                      # service ids are strings, to distinguish them from the real ones.
         | 
| 256 | 
            +
                      # In particular processId is also a BSON::ObjectId, but will be
         | 
| 257 | 
            +
                      # mapped to a string for clarity that this is a fake service id.
         | 
| 258 | 
            +
                      if ok? && !service_id
         | 
| 259 | 
            +
                        unless force_load_balancer
         | 
| 260 | 
            +
                          raise Error::MissingServiceId, "The server at #{address.seed} did not provide a service id in handshake response"
         | 
| 261 | 
            +
                        end
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                        fake_service_id = if process_id = topology_version && topology_version['processId']
         | 
| 264 | 
            +
                          "process:#{process_id}"
         | 
| 265 | 
            +
                        else
         | 
| 266 | 
            +
                          "fake:#{rand(2**32-1)+1}"
         | 
| 267 | 
            +
                        end
         | 
| 268 | 
            +
                        @config = @config.merge('serviceId' => fake_service_id)
         | 
| 269 | 
            +
                      end
         | 
| 270 | 
            +
                    end
         | 
| 271 | 
            +
             | 
| 223 272 | 
             
                    if Mongo::Lint.enabled?
         | 
| 224 273 | 
             
                      # prepopulate cache instance variables
         | 
| 225 274 | 
             
                      hosts
         | 
| @@ -237,11 +286,23 @@ module Mongo | |
| 237 286 | 
             
                  # @return [ Hash ] The actual result from the hello command.
         | 
| 238 287 | 
             
                  attr_reader :config
         | 
| 239 288 |  | 
| 289 | 
            +
                  # Returns whether this server is a load balancer.
         | 
| 290 | 
            +
                  #
         | 
| 291 | 
            +
                  # @return [ true | false ] Whether this server is a load balancer.
         | 
| 292 | 
            +
                  def load_balancer?
         | 
| 293 | 
            +
                    @load_balancer
         | 
| 294 | 
            +
                  end
         | 
| 295 | 
            +
             | 
| 240 296 | 
             
                  # @return [ Features ] features The features for the server.
         | 
| 241 297 | 
             
                  def features
         | 
| 242 298 | 
             
                    @features
         | 
| 243 299 | 
             
                  end
         | 
| 244 300 |  | 
| 301 | 
            +
                  # @return [ nil | Object ] The service id, if any.
         | 
| 302 | 
            +
                  def service_id
         | 
| 303 | 
            +
                    config['serviceId']
         | 
| 304 | 
            +
                  end
         | 
| 305 | 
            +
             | 
| 245 306 | 
             
                  # @return [ Float ] The moving average time the hello call took to complete.
         | 
| 246 307 | 
             
                  attr_reader :average_round_trip_time
         | 
| 247 308 |  | 
| @@ -625,6 +686,7 @@ module Mongo | |
| 625 686 | 
             
                  #
         | 
| 626 687 | 
             
                  # @since 2.4.0
         | 
| 627 688 | 
             
                  def server_type
         | 
| 689 | 
            +
                    return :load_balancer if load_balancer?
         | 
| 628 690 | 
             
                    return :arbiter if arbiter?
         | 
| 629 691 | 
             
                    return :ghost if ghost?
         | 
| 630 692 | 
             
                    return :sharded if mongos?
         | 
| @@ -659,6 +721,7 @@ module Mongo | |
| 659 721 | 
             
                  #
         | 
| 660 722 | 
             
                  # @since 2.0.0
         | 
| 661 723 | 
             
                  def unknown?
         | 
| 724 | 
            +
                    return false if load_balancer?
         | 
| 662 725 | 
             
                    config.empty? || config.keys == %w(topologyVersion) || !ok?
         | 
| 663 726 | 
             
                  end
         | 
| 664 727 |  | 
| @@ -780,6 +843,11 @@ module Mongo | |
| 780 843 | 
             
                    config['connectionId']
         | 
| 781 844 | 
             
                  end
         | 
| 782 845 |  | 
| 846 | 
            +
                  # @api experimental
         | 
| 847 | 
            +
                  def service_id
         | 
| 848 | 
            +
                    config['serviceId']
         | 
| 849 | 
            +
                  end
         | 
| 850 | 
            +
             | 
| 783 851 | 
             
                  # Check equality of two descriptions.
         | 
| 784 852 | 
             
                  #
         | 
| 785 853 | 
             
                  # @example Check description equality.
         | 
| @@ -825,8 +893,19 @@ module Mongo | |
| 825 893 | 
             
                        raise ArgumentError, "Bogus required version #{version}"
         | 
| 826 894 | 
             
                      end
         | 
| 827 895 |  | 
| 896 | 
            +
                    if load_balancer?
         | 
| 897 | 
            +
                      # If we are talking to a load balancer, there is no monitoring
         | 
| 898 | 
            +
                      # and we don't know what server is behind the load balancer.
         | 
| 899 | 
            +
                      # Assume everything is supported.
         | 
| 900 | 
            +
                      # TODO remove this when RUBY-2220 is implemented.
         | 
| 901 | 
            +
                      return true
         | 
| 902 | 
            +
                    end
         | 
| 903 | 
            +
             | 
| 828 904 | 
             
                    required_wv >= min_wire_version && required_wv <= max_wire_version
         | 
| 829 905 | 
             
                  end
         | 
| 830 906 | 
             
                end
         | 
| 831 907 | 
             
              end
         | 
| 832 908 | 
             
            end
         | 
| 909 | 
            +
             | 
| 910 | 
            +
            require 'mongo/server/description/features'
         | 
| 911 | 
            +
            require 'mongo/server/description/load_balancer'
         | 
| @@ -194,13 +194,12 @@ module Mongo | |
| 194 194 | 
             
                    #
         | 
| 195 195 | 
             
                    # @raise [Mongo::Error] If handshake failed.
         | 
| 196 196 | 
             
                    def handshake!
         | 
| 197 | 
            -
                       | 
| 198 | 
            -
                         | 
| 199 | 
            -
             | 
| 197 | 
            +
                      command = handshake_command(
         | 
| 198 | 
            +
                        handshake_document(
         | 
| 199 | 
            +
                          @app_metadata,
         | 
| 200 | 
            +
                          server_api: options[:server_api]
         | 
| 201 | 
            +
                        )
         | 
| 200 202 | 
             
                      )
         | 
| 201 | 
            -
                      # TODO (DR): OP_MSG should be used if api version is declared.
         | 
| 202 | 
            -
                      # See https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst#id5
         | 
| 203 | 
            -
                      command = Protocol::Query.new(Database::ADMIN, Database::COMMAND, document, :limit => -1)
         | 
| 204 203 | 
             
                      payload = command.serialize.to_s
         | 
| 205 204 | 
             
                      message = dispatch_bytes(payload)
         | 
| 206 205 | 
             
                      result = Operation::Result.new(message)
         | 
    
        data/lib/mongo/server/monitor.rb
    CHANGED
    
    | @@ -215,7 +215,8 @@ module Mongo | |
| 215 215 | 
             
                      old_description = server.description
         | 
| 216 216 |  | 
| 217 217 | 
             
                      new_description = Description.new(server.address, result,
         | 
| 218 | 
            -
                        server.round_trip_time_averager.average_round_trip_time | 
| 218 | 
            +
                        average_round_trip_time: server.round_trip_time_averager.average_round_trip_time
         | 
| 219 | 
            +
                      )
         | 
| 219 220 |  | 
| 220 221 | 
             
                      server.cluster.run_sdam_flow(server.description, new_description, awaited: awaited)
         | 
| 221 222 |  | 
| @@ -71,32 +71,41 @@ module Mongo | |
| 71 71 | 
             
                      raise Error::InternalDriverError, "Connection description cannot be unknown after successful handshake: #{description.inspect}"
         | 
| 72 72 | 
             
                    end
         | 
| 73 73 |  | 
| 74 | 
            -
                     | 
| 75 | 
            -
                       | 
| 76 | 
            -
                         | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
                         | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
                         | 
| 86 | 
            -
                           | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
                         | 
| 74 | 
            +
                    begin
         | 
| 75 | 
            +
                      if speculative_auth_doc && (speculative_auth_result = result['speculativeAuthenticate'])
         | 
| 76 | 
            +
                        unless description.features.scram_sha_1_enabled?
         | 
| 77 | 
            +
                          raise Error::InvalidServerAuthResponse, "Speculative auth succeeded on a pre-3.0 server"
         | 
| 78 | 
            +
                        end
         | 
| 79 | 
            +
                        case speculative_auth_user.mechanism
         | 
| 80 | 
            +
                        when :mongodb_x509
         | 
| 81 | 
            +
                          # Done
         | 
| 82 | 
            +
                        # We default auth mechanism to scram256, but if user specified
         | 
| 83 | 
            +
                        # scram explicitly we may be able to authenticate speculatively
         | 
| 84 | 
            +
                        # with scram.
         | 
| 85 | 
            +
                        when :scram, :scram256
         | 
| 86 | 
            +
                          authenticate!(
         | 
| 87 | 
            +
                            speculative_auth_client_nonce: speculative_auth.conversation.client_nonce,
         | 
| 88 | 
            +
                            speculative_auth_mech: speculative_auth_user.mechanism,
         | 
| 89 | 
            +
                            speculative_auth_result: speculative_auth_result,
         | 
| 90 | 
            +
                          )
         | 
| 91 | 
            +
                        else
         | 
| 92 | 
            +
                          raise Error::InternalDriverError, "Speculative auth unexpectedly succeeded for mechanism #{speculative_auth_user.mechanism.inspect}"
         | 
| 93 | 
            +
                        end
         | 
| 94 | 
            +
                      elsif !description.arbiter?
         | 
| 95 | 
            +
                        authenticate!
         | 
| 92 96 | 
             
                      end
         | 
| 93 | 
            -
                     | 
| 94 | 
            -
                       | 
| 97 | 
            +
                    rescue Mongo::Error, Mongo::Error::AuthError => exc
         | 
| 98 | 
            +
                      exc.service_id = service_id
         | 
| 99 | 
            +
                      raise
         | 
| 95 100 | 
             
                    end
         | 
| 96 101 |  | 
| 97 102 | 
             
                    if description.unknown?
         | 
| 98 103 | 
             
                      raise Error::InternalDriverError, "Connection description cannot be unknown after successful authentication: #{description.inspect}"
         | 
| 99 104 | 
             
                    end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    if server.load_balancer? && !description.mongos?
         | 
| 107 | 
            +
                      raise Error::BadLoadBalancerTarget, "Load-balanced operation requires being connected a mongos, but the server at #{address.seed} reported itself as #{description.server_type.to_s.gsub('_', ' ')}"
         | 
| 108 | 
            +
                    end
         | 
| 100 109 | 
             
                  end
         | 
| 101 110 |  | 
| 102 111 | 
             
                  private
         | 
| @@ -111,16 +120,14 @@ module Mongo | |
| 111 120 | 
             
                      raise Error::InternalDriverError, "Cannot handshake because there is no usable socket (for #{address})"
         | 
| 112 121 | 
             
                    end
         | 
| 113 122 |  | 
| 114 | 
            -
                     | 
| 115 | 
            -
                       | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 123 | 
            +
                    hello_command = handshake_command(
         | 
| 124 | 
            +
                      handshake_document(
         | 
| 125 | 
            +
                        app_metadata,
         | 
| 126 | 
            +
                        speculative_auth_doc: speculative_auth_doc,
         | 
| 127 | 
            +
                        load_balancer: server.load_balancer?,
         | 
| 128 | 
            +
                        server_api: options[:server_api]
         | 
| 129 | 
            +
                      )
         | 
| 118 130 | 
             
                    )
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                    # TODO (DR): OP_MSG should be used if api version is declared.
         | 
| 121 | 
            -
                    # See https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst#id5
         | 
| 122 | 
            -
                    hello_command = Protocol::Query.new(Database::ADMIN, Database::COMMAND, hello_doc, :limit => -1)
         | 
| 123 | 
            -
             | 
| 124 131 | 
             
                    doc = nil
         | 
| 125 132 | 
             
                    @server.handle_handshake_failure! do
         | 
| 126 133 | 
             
                      begin
         | 
| @@ -144,6 +151,10 @@ module Mongo | |
| 144 151 | 
             
                      end
         | 
| 145 152 | 
             
                    end
         | 
| 146 153 |  | 
| 154 | 
            +
                    if @server.force_load_balancer?
         | 
| 155 | 
            +
                      doc['serviceId'] ||= "fake:#{rand(2**32-1)+1}"
         | 
| 156 | 
            +
                    end
         | 
| 157 | 
            +
             | 
| 147 158 | 
             
                    post_handshake(doc, @server.round_trip_time_averager.average_round_trip_time)
         | 
| 148 159 |  | 
| 149 160 | 
             
                    doc
         | 
| @@ -193,7 +204,7 @@ module Mongo | |
| 193 204 | 
             
                  # This is a separate method to keep the nesting level down.
         | 
| 194 205 | 
             
                  #
         | 
| 195 206 | 
             
                  # @return [ Server::Description ] The server description calculated from
         | 
| 196 | 
            -
                  #    | 
| 207 | 
            +
                  #   the handshake response for this particular connection.
         | 
| 197 208 | 
             
                  def post_handshake(response, average_rtt)
         | 
| 198 209 | 
             
                    if response["ok"] == 1
         | 
| 199 210 | 
             
                      # Auth mechanism is entirely dependent on the contents of
         | 
| @@ -210,7 +221,12 @@ module Mongo | |
| 210 221 | 
             
                      @sasl_supported_mechanisms = nil
         | 
| 211 222 | 
             
                    end
         | 
| 212 223 |  | 
| 213 | 
            -
                    @description = Description.new( | 
| 224 | 
            +
                    @description = Description.new(
         | 
| 225 | 
            +
                      address, response,
         | 
| 226 | 
            +
                      average_round_trip_time: average_rtt,
         | 
| 227 | 
            +
                      load_balancer: server.load_balancer?,
         | 
| 228 | 
            +
                      force_load_balancer: options[:connect] == :load_balanced,
         | 
| 229 | 
            +
                    ).tap do |new_description|
         | 
| 214 230 | 
             
                      @server.cluster.run_sdam_flow(@server.description, new_description)
         | 
| 215 231 | 
             
                    end
         | 
| 216 232 | 
             
                  end
         |