mongo 2.8.0 → 2.9.0.rc0
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.tar.gz.sig +0 -0
 - data/Rakefile +12 -0
 - data/lib/mongo.rb +15 -1
 - data/lib/mongo/address/ipv6.rb +0 -2
 - data/lib/mongo/auth/scram/conversation.rb +0 -3
 - data/lib/mongo/bulk_write/result_combiner.rb +12 -2
 - data/lib/mongo/client.rb +59 -6
 - data/lib/mongo/cluster.rb +19 -8
 - data/lib/mongo/cluster/reapers/cursor_reaper.rb +0 -2
 - data/lib/mongo/cluster/reapers/socket_reaper.rb +12 -9
 - data/lib/mongo/collection.rb +1 -1
 - data/lib/mongo/collection/view/aggregation.rb +5 -1
 - data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
 - data/lib/mongo/collection/view/change_stream.rb +30 -10
 - data/lib/mongo/collection/view/iterable.rb +13 -6
 - data/lib/mongo/collection/view/map_reduce.rb +12 -10
 - data/lib/mongo/collection/view/readable.rb +19 -14
 - data/lib/mongo/cursor.rb +12 -8
 - data/lib/mongo/database.rb +10 -7
 - data/lib/mongo/database/view.rb +18 -11
 - data/lib/mongo/error.rb +2 -2
 - data/lib/mongo/error/connection_check_out_timeout.rb +49 -0
 - data/lib/mongo/error/operation_failure.rb +9 -9
 - data/lib/mongo/error/parser.rb +25 -3
 - data/lib/mongo/error/pool_closed_error.rb +43 -0
 - data/lib/mongo/error/sdam_error_detection.rb +18 -0
 - data/lib/mongo/grid/file/chunk.rb +0 -2
 - data/lib/mongo/grid/fs_bucket.rb +26 -12
 - data/lib/mongo/grid/stream/read.rb +36 -21
 - data/lib/mongo/index/view.rb +11 -7
 - data/lib/mongo/logger.rb +0 -2
 - data/lib/mongo/monitoring.rb +31 -0
 - data/lib/mongo/monitoring/cmap_log_subscriber.rb +53 -0
 - data/lib/mongo/monitoring/event.rb +1 -0
 - data/lib/mongo/monitoring/event/cmap.rb +25 -0
 - data/lib/mongo/monitoring/event/cmap/base.rb +28 -0
 - data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +78 -0
 - data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +56 -0
 - data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +63 -0
 - data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +64 -0
 - data/lib/mongo/monitoring/event/cmap/connection_closed.rb +103 -0
 - data/lib/mongo/monitoring/event/cmap/connection_created.rb +64 -0
 - data/lib/mongo/monitoring/event/cmap/connection_ready.rb +64 -0
 - data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +57 -0
 - data/lib/mongo/monitoring/event/cmap/pool_closed.rb +57 -0
 - data/lib/mongo/monitoring/event/cmap/pool_created.rb +63 -0
 - data/lib/mongo/monitoring/event/command_started.rb +12 -3
 - data/lib/mongo/monitoring/publishable.rb +10 -2
 - data/lib/mongo/operation.rb +0 -1
 - data/lib/mongo/operation/find/legacy/result.rb +1 -0
 - data/lib/mongo/operation/list_collections/result.rb +7 -1
 - data/lib/mongo/operation/result.rb +10 -1
 - data/lib/mongo/operation/shared/executable.rb +15 -0
 - data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +29 -0
 - data/lib/mongo/operation/shared/specifiable.rb +0 -16
 - data/lib/mongo/operation/update/legacy/result.rb +1 -0
 - data/lib/mongo/protocol/compressed.rb +0 -2
 - data/lib/mongo/protocol/msg.rb +25 -2
 - data/lib/mongo/retryable.rb +171 -33
 - data/lib/mongo/server.rb +26 -7
 - data/lib/mongo/server/app_metadata.rb +0 -2
 - data/lib/mongo/server/connectable.rb +8 -2
 - data/lib/mongo/server/connection.rb +83 -13
 - data/lib/mongo/server/connection_base.rb +1 -1
 - data/lib/mongo/server/connection_pool.rb +439 -43
 - data/lib/mongo/server/monitor/connection.rb +4 -1
 - data/lib/mongo/session.rb +37 -5
 - data/lib/mongo/session/session_pool.rb +2 -2
 - data/lib/mongo/socket.rb +0 -2
 - data/lib/mongo/socket/ssl.rb +0 -2
 - data/lib/mongo/uri.rb +127 -66
 - data/lib/mongo/uri/srv_protocol.rb +35 -13
 - data/lib/mongo/version.rb +1 -1
 - data/spec/README.md +190 -63
 - data/spec/integration/change_stream_spec.rb +64 -0
 - data/spec/integration/command_spec.rb +0 -7
 - data/spec/integration/error_detection_spec.rb +39 -0
 - data/spec/integration/read_concern.rb +83 -0
 - data/spec/integration/retryable_writes_spec.rb +6 -50
 - data/spec/integration/sdam_error_handling_spec.rb +60 -7
 - data/spec/integration/ssl_uri_options_spec.rb +24 -0
 - data/spec/integration/step_down_spec.rb +197 -0
 - data/spec/lite_spec_helper.rb +4 -0
 - data/spec/mongo/client_construction_spec.rb +42 -17
 - data/spec/mongo/client_spec.rb +32 -1
 - data/spec/mongo/cluster/socket_reaper_spec.rb +2 -2
 - data/spec/mongo/cluster_spec.rb +36 -2
 - data/spec/mongo/collection/view/aggregation_spec.rb +2 -0
 - data/spec/mongo/collection/view/change_stream_spec.rb +28 -28
 - data/spec/mongo/collection/view/readable_spec.rb +1 -1
 - data/spec/mongo/collection/view_spec.rb +3 -1
 - data/spec/mongo/cursor_spec.rb +5 -5
 - data/spec/mongo/error/parser_spec.rb +61 -1
 - data/spec/mongo/grid/stream/read_spec.rb +2 -2
 - data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +23 -0
 - data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +19 -0
 - data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +23 -0
 - data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +23 -0
 - data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +27 -0
 - data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +24 -0
 - data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +24 -0
 - data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +19 -0
 - data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +19 -0
 - data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +26 -0
 - data/spec/mongo/operation/delete/bulk_spec.rb +1 -6
 - data/spec/mongo/operation/delete/command_spec.rb +1 -1
 - data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
 - data/spec/mongo/operation/delete_spec.rb +4 -4
 - data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
 - data/spec/mongo/operation/insert/command_spec.rb +1 -1
 - data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
 - data/spec/mongo/operation/update/bulk_spec.rb +1 -1
 - data/spec/mongo/operation/update/command_spec.rb +2 -2
 - data/spec/mongo/operation/update/op_msg_spec.rb +2 -2
 - data/spec/mongo/protocol/msg_spec.rb +11 -0
 - data/spec/mongo/retryable_spec.rb +78 -25
 - data/spec/mongo/server/connection_pool_spec.rb +661 -126
 - data/spec/mongo/server/connection_spec.rb +55 -7
 - data/spec/mongo/server_spec.rb +5 -0
 - data/spec/mongo/uri/srv_protocol_spec.rb +135 -2
 - data/spec/mongo/uri_option_parsing_spec.rb +511 -0
 - data/spec/mongo/uri_spec.rb +42 -6
 - data/spec/spec_helper.rb +1 -84
 - data/spec/spec_tests/cmap_spec.rb +50 -0
 - data/spec/spec_tests/command_monitoring_spec.rb +7 -18
 - data/spec/spec_tests/crud_spec.rb +3 -49
 - data/spec/spec_tests/data/cmap/connection-must-have-id.yml +21 -0
 - data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +21 -0
 - data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +24 -0
 - data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +24 -0
 - data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +21 -0
 - data/spec/spec_tests/data/cmap/pool-checkin.yml +18 -0
 - data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +13 -0
 - data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +28 -0
 - data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +34 -0
 - data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +31 -0
 - data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +29 -0
 - data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +26 -0
 - data/spec/spec_tests/data/cmap/pool-close.yml +11 -0
 - data/spec/spec_tests/data/cmap/pool-create-max-size.yml +56 -0
 - data/spec/spec_tests/data/cmap/pool-create-min-size.yml +27 -0
 - data/spec/spec_tests/data/cmap/pool-create-with-options.yml +20 -0
 - data/spec/spec_tests/data/cmap/pool-create.yml +12 -0
 - data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +94 -0
 - data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +41 -0
 - data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +157 -0
 - data/spec/spec_tests/data/retryable_reads/aggregate.yml +87 -0
 - data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +149 -0
 - data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +61 -0
 - data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +149 -0
 - data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +65 -0
 - data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +153 -0
 - data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +61 -0
 - data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +150 -0
 - data/spec/spec_tests/data/retryable_reads/count.yml +64 -0
 - data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +150 -0
 - data/spec/spec_tests/data/retryable_reads/countDocuments.yml +64 -0
 - data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +156 -0
 - data/spec/spec_tests/data/retryable_reads/distinct.yml +71 -0
 - data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +148 -0
 - data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount.yml +62 -0
 - data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +160 -0
 - data/spec/spec_tests/data/retryable_reads/find.yml +86 -0
 - data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +154 -0
 - data/spec/spec_tests/data/retryable_reads/findOne.yml +68 -0
 - data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +173 -0
 - data/spec/spec_tests/data/retryable_reads/gridfs-download.yml +79 -0
 - data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +174 -0
 - data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName.yml +79 -0
 - data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +143 -0
 - data/spec/spec_tests/data/retryable_reads/listCollectionNames.yml +59 -0
 - data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +144 -0
 - data/spec/spec_tests/data/retryable_reads/listCollectionObjects.yml +59 -0
 - data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +143 -0
 - data/spec/spec_tests/data/retryable_reads/listCollections.yml +59 -0
 - data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +143 -0
 - data/spec/spec_tests/data/retryable_reads/listDatabaseNames.yml +59 -0
 - data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +144 -0
 - data/spec/spec_tests/data/retryable_reads/listDatabaseObjects.yml +59 -0
 - data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +144 -0
 - data/spec/spec_tests/data/retryable_reads/listDatabases.yml +59 -0
 - data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +144 -0
 - data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +60 -0
 - data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +145 -0
 - data/spec/spec_tests/data/retryable_reads/listIndexes.yml +60 -0
 - data/spec/spec_tests/data/retryable_reads/mapReduce.yml +60 -0
 - data/spec/spec_tests/data/retryable_writes/bulkWrite-serverErrors.yml +10 -7
 - data/spec/spec_tests/data/retryable_writes/bulkWrite.yml +15 -22
 - data/spec/spec_tests/data/retryable_writes/deleteMany.yml +22 -0
 - data/spec/spec_tests/data/retryable_writes/deleteOne-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/deleteOne.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/findOneAndDelete-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/findOneAndDelete.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/findOneAndReplace-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/findOneAndReplace.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/findOneAndUpdate.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/insertMany-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/insertMany.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +10 -45
 - data/spec/spec_tests/data/retryable_writes/insertOne.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/replaceOne-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/replaceOne.yml +5 -8
 - data/spec/spec_tests/data/retryable_writes/updateMany.yml +27 -0
 - data/spec/spec_tests/data/retryable_writes/updateOne-serverErrors.yml +8 -7
 - data/spec/spec_tests/data/retryable_writes/updateOne.yml +5 -14
 - data/spec/spec_tests/data/transactions/abort.yml +7 -2
 - data/spec/spec_tests/data/transactions/bulk.yml +7 -2
 - data/spec/spec_tests/data/transactions/causal-consistency.yml +11 -4
 - data/spec/spec_tests/data/transactions/commit.yml +11 -4
 - data/spec/spec_tests/data/transactions/count.yml +64 -0
 - data/spec/spec_tests/data/transactions/delete.yml +7 -2
 - data/spec/spec_tests/data/transactions/error-labels.yml +8 -2
 - data/spec/spec_tests/data/transactions/errors.yml +7 -2
 - data/spec/spec_tests/data/transactions/findOneAndDelete.yml +7 -2
 - data/spec/spec_tests/data/transactions/findOneAndReplace.yml +7 -2
 - data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +7 -2
 - data/spec/spec_tests/data/transactions/insert.yml +9 -2
 - data/spec/spec_tests/data/transactions/isolation.yml +7 -2
 - data/spec/spec_tests/data/transactions/read-concern.yml +15 -6
 - data/spec/spec_tests/data/transactions/read-pref.yml +7 -2
 - data/spec/spec_tests/data/transactions/reads.yml +8 -48
 - data/spec/spec_tests/data/transactions/retryable-abort.yml +7 -2
 - data/spec/spec_tests/data/transactions/retryable-commit.yml +7 -2
 - data/spec/spec_tests/data/transactions/retryable-writes.yml +7 -2
 - data/spec/spec_tests/data/transactions/run-command.yml +7 -2
 - data/spec/spec_tests/data/transactions/transaction-options.yml +7 -2
 - data/spec/spec_tests/data/transactions/update.yml +7 -2
 - data/spec/spec_tests/data/transactions/write-concern.yml +7 -2
 - data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/callback-commits.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/callback-retry.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/commit-retry.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +6 -3
 - data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/commit.yml +6 -1
 - data/spec/spec_tests/data/transactions_api/transaction-options.yml +6 -1
 - data/spec/spec_tests/retryable_reads_spec.rb +11 -0
 - data/spec/spec_tests/retryable_writes_spec.rb +4 -69
 - data/spec/spec_tests/transactions_api_spec.rb +42 -37
 - data/spec/spec_tests/transactions_spec.rb +42 -33
 - data/spec/support/authorization.rb +12 -0
 - data/spec/support/change_streams/operation.rb +1 -1
 - data/spec/support/client_registry.rb +20 -0
 - data/spec/support/cluster_config.rb +16 -15
 - data/spec/support/cluster_tools.rb +346 -0
 - data/spec/support/cmap.rb +367 -0
 - data/spec/support/cmap/verifier.rb +46 -0
 - data/spec/support/command_monitoring.rb +4 -6
 - data/spec/support/common_shortcuts.rb +6 -0
 - data/spec/support/connection_string.rb +2 -2
 - data/spec/support/crud.rb +171 -184
 - data/spec/support/crud/operation.rb +43 -0
 - data/spec/support/crud/outcome.rb +53 -0
 - data/spec/support/crud/read.rb +102 -12
 - data/spec/support/crud/requirement.rb +69 -0
 - data/spec/support/crud/spec.rb +68 -0
 - data/spec/support/crud/test.rb +141 -0
 - data/spec/support/crud/verifier.rb +96 -18
 - data/spec/support/crud/write.rb +18 -3
 - data/spec/support/event_subscriber.rb +15 -0
 - data/spec/support/primary_socket.rb +2 -2
 - data/spec/support/spec_config.rb +89 -20
 - data/spec/support/transactions.rb +2 -306
 - data/spec/support/transactions/operation.rb +7 -7
 - data/spec/support/transactions/spec.rb +28 -0
 - data/spec/support/transactions/test.rb +191 -0
 - data/spec/support/utils.rb +123 -0
 - metadata +202 -9
 - metadata.gz.sig +0 -0
 - data/lib/mongo/server/connection_pool/queue.rb +0 -359
 - data/spec/mongo/server/connection_pool/queue_spec.rb +0 -353
 - data/spec/support/transactions/verifier.rb +0 -97
 
    
        data/lib/mongo/protocol/msg.rb
    CHANGED
    
    | 
         @@ -31,6 +31,12 @@ module Mongo 
     | 
|
| 
       31 
31 
     | 
    
         
             
                  # @since 2.5.0
         
     | 
| 
       32 
32 
     | 
    
         
             
                  DATABASE_IDENTIFIER = '$db'.freeze
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
                  # Keys that the driver adds to commands. These are going to be
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # moved to the end of the hash for better logging.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 38 
     | 
    
         
            +
                  INTERNAL_KEYS = Set.new(%w($clusterTime lsid signature txnNumber)).freeze
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
       34 
40 
     | 
    
         
             
                  # Creates a new OP_MSG protocol message
         
     | 
| 
       35 
41 
     | 
    
         
             
                  #
         
     | 
| 
       36 
42 
     | 
    
         
             
                  # @example Create a OP_MSG wire protocol message
         
     | 
| 
         @@ -82,10 +88,27 @@ module Mongo 
     | 
|
| 
       82 
88 
     | 
    
         
             
                  #
         
     | 
| 
       83 
89 
     | 
    
         
             
                  # @since 2.5.0
         
     | 
| 
       84 
90 
     | 
    
         
             
                  def payload
         
     | 
| 
      
 91 
     | 
    
         
            +
                    # Reorder keys in global_args for better logging - see
         
     | 
| 
      
 92 
     | 
    
         
            +
                    # https://jira.mongodb.org/browse/RUBY-1591.
         
     | 
| 
      
 93 
     | 
    
         
            +
                    # Note that even without the reordering, the payload is not an exact
         
     | 
| 
      
 94 
     | 
    
         
            +
                    # match to what is sent over the wire because the command as used in
         
     | 
| 
      
 95 
     | 
    
         
            +
                    # the published eent combines keys from multiple sections of the
         
     | 
| 
      
 96 
     | 
    
         
            +
                    # payload sent over the wire.
         
     | 
| 
      
 97 
     | 
    
         
            +
                    ordered_command = {}
         
     | 
| 
      
 98 
     | 
    
         
            +
                    skipped_command = {}
         
     | 
| 
      
 99 
     | 
    
         
            +
                    command.each do |k, v|
         
     | 
| 
      
 100 
     | 
    
         
            +
                      if INTERNAL_KEYS.member?(k.to_s)
         
     | 
| 
      
 101 
     | 
    
         
            +
                        skipped_command[k] = v
         
     | 
| 
      
 102 
     | 
    
         
            +
                      else
         
     | 
| 
      
 103 
     | 
    
         
            +
                        ordered_command[k] = v
         
     | 
| 
      
 104 
     | 
    
         
            +
                      end
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                    ordered_command.update(skipped_command)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
       85 
108 
     | 
    
         
             
                    BSON::Document.new(
         
     | 
| 
       86 
     | 
    
         
            -
                      command_name:  
     | 
| 
      
 109 
     | 
    
         
            +
                      command_name: ordered_command.keys.first.to_s,
         
     | 
| 
       87 
110 
     | 
    
         
             
                      database_name: global_args[DATABASE_IDENTIFIER],
         
     | 
| 
       88 
     | 
    
         
            -
                      command:  
     | 
| 
      
 111 
     | 
    
         
            +
                      command: ordered_command,
         
     | 
| 
       89 
112 
     | 
    
         
             
                      request_id: request_id,
         
     | 
| 
       90 
113 
     | 
    
         
             
                      reply: sections[0]
         
     | 
| 
       91 
114 
     | 
    
         
             
                    )
         
     | 
    
        data/lib/mongo/retryable.rb
    CHANGED
    
    | 
         @@ -19,50 +19,115 @@ module Mongo 
     | 
|
| 
       19 
19 
     | 
    
         
             
              # @since 2.1.0
         
     | 
| 
       20 
20 
     | 
    
         
             
              module Retryable
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                # Execute a read operation  
     | 
| 
      
 22 
     | 
    
         
            +
                # Execute a read operation returning a cursor with retrying.
         
     | 
| 
      
 23 
     | 
    
         
            +
                #
         
     | 
| 
      
 24 
     | 
    
         
            +
                # This method performs server selection for the specified server selector
         
     | 
| 
      
 25 
     | 
    
         
            +
                # and yields to the provided block, which should execute the initial
         
     | 
| 
      
 26 
     | 
    
         
            +
                # query operation and return its result. The block will be passed the
         
     | 
| 
      
 27 
     | 
    
         
            +
                # server selected for the operation. If the block raises an exception,
         
     | 
| 
      
 28 
     | 
    
         
            +
                # and this exception corresponds to a read retryable error, and read
         
     | 
| 
      
 29 
     | 
    
         
            +
                # retries are enabled for the client, this method will perform server
         
     | 
| 
      
 30 
     | 
    
         
            +
                # selection again and yield to the block again (with potentially a
         
     | 
| 
      
 31 
     | 
    
         
            +
                # different server). If the block returns successfully, the result
         
     | 
| 
      
 32 
     | 
    
         
            +
                # of the block (which should be a Mongo::Operation::Result) is used to
         
     | 
| 
      
 33 
     | 
    
         
            +
                # construct a Mongo::Cursor object for the result set. The cursor
         
     | 
| 
      
 34 
     | 
    
         
            +
                # is then returned.
         
     | 
| 
      
 35 
     | 
    
         
            +
                #
         
     | 
| 
      
 36 
     | 
    
         
            +
                # If modern retry reads are on (which is the default), the initial read
         
     | 
| 
      
 37 
     | 
    
         
            +
                # operation will be retried once. If legacy retry reads are on, the
         
     | 
| 
      
 38 
     | 
    
         
            +
                # initial read operation will be retried zero or more times depending
         
     | 
| 
      
 39 
     | 
    
         
            +
                # on the :max_read_retries client setting, the default for which is 1.
         
     | 
| 
      
 40 
     | 
    
         
            +
                # To disable read retries, turn off modern read retries by setting
         
     | 
| 
      
 41 
     | 
    
         
            +
                # retry_reads: false and set :max_read_retries to 0 on the client.
         
     | 
| 
       23 
42 
     | 
    
         
             
                #
         
     | 
| 
       24 
43 
     | 
    
         
             
                # @api private
         
     | 
| 
       25 
44 
     | 
    
         
             
                #
         
     | 
| 
       26 
     | 
    
         
            -
                # @example Execute  
     | 
| 
       27 
     | 
    
         
            -
                #    
     | 
| 
      
 45 
     | 
    
         
            +
                # @example Execute a read returning a cursor.
         
     | 
| 
      
 46 
     | 
    
         
            +
                #   cursor = read_with_retry_cursor(session, server_selector, view) do |server|
         
     | 
| 
      
 47 
     | 
    
         
            +
                #     # return a Mongo::Operation::Result
         
     | 
| 
       28 
48 
     | 
    
         
             
                #     ...
         
     | 
| 
       29 
49 
     | 
    
         
             
                #   end
         
     | 
| 
       30 
50 
     | 
    
         
             
                #
         
     | 
| 
       31 
     | 
    
         
            -
                # @ 
     | 
| 
      
 51 
     | 
    
         
            +
                # @param [ Mongo::Session ] session The session that the operation is being
         
     | 
| 
      
 52 
     | 
    
         
            +
                #   run on.
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @param [ Mongo::ServerSelector::Selectable ] server_selector Server
         
     | 
| 
      
 54 
     | 
    
         
            +
                #   selector for the operation.
         
     | 
| 
      
 55 
     | 
    
         
            +
                # @param [ CollectionView ] view The +CollectionView+ defining the query.
         
     | 
| 
      
 56 
     | 
    
         
            +
                # @param [ Proc ] block The block to execute.
         
     | 
| 
      
 57 
     | 
    
         
            +
                #
         
     | 
| 
      
 58 
     | 
    
         
            +
                # @return [ Cursor ] The cursor for the result set.
         
     | 
| 
      
 59 
     | 
    
         
            +
                def read_with_retry_cursor(session, server_selector, view, &block)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  read_with_retry(session, server_selector) do |server|
         
     | 
| 
      
 61 
     | 
    
         
            +
                    result = yield server
         
     | 
| 
      
 62 
     | 
    
         
            +
                    Cursor.new(view, result, server, session: session)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                # Execute a read operation with retrying.
         
     | 
| 
      
 67 
     | 
    
         
            +
                #
         
     | 
| 
      
 68 
     | 
    
         
            +
                # This method performs server selection for the specified server selector
         
     | 
| 
      
 69 
     | 
    
         
            +
                # and yields to the provided block, which should execute the initial
         
     | 
| 
      
 70 
     | 
    
         
            +
                # query operation and return its result. The block will be passed the
         
     | 
| 
      
 71 
     | 
    
         
            +
                # server selected for the operation. If the block raises an exception,
         
     | 
| 
      
 72 
     | 
    
         
            +
                # and this exception corresponds to a read retryable error, and read
         
     | 
| 
      
 73 
     | 
    
         
            +
                # retries are enabled for the client, this method will perform server
         
     | 
| 
      
 74 
     | 
    
         
            +
                # selection again and yield to the block again (with potentially a
         
     | 
| 
      
 75 
     | 
    
         
            +
                # different server). If the block returns successfully, the result
         
     | 
| 
      
 76 
     | 
    
         
            +
                # of the block is returned.
         
     | 
| 
       32 
77 
     | 
    
         
             
                #
         
     | 
| 
       33 
     | 
    
         
            -
                #  
     | 
| 
      
 78 
     | 
    
         
            +
                # If modern retry reads are on (which is the default), the initial read
         
     | 
| 
      
 79 
     | 
    
         
            +
                # operation will be retried once. If legacy retry reads are on, the
         
     | 
| 
      
 80 
     | 
    
         
            +
                # initial read operation will be retried zero or more times depending
         
     | 
| 
      
 81 
     | 
    
         
            +
                # on the :max_read_retries client setting, the default for which is 1.
         
     | 
| 
      
 82 
     | 
    
         
            +
                # To disable read retries, turn off modern read retries by setting
         
     | 
| 
      
 83 
     | 
    
         
            +
                # retry_reads: false and set :max_read_retries to 0 on the client.
         
     | 
| 
      
 84 
     | 
    
         
            +
                #
         
     | 
| 
      
 85 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 86 
     | 
    
         
            +
                #
         
     | 
| 
      
 87 
     | 
    
         
            +
                # @example Execute the read.
         
     | 
| 
      
 88 
     | 
    
         
            +
                #   read_with_retry(session, server_selector) do |server|
         
     | 
| 
      
 89 
     | 
    
         
            +
                #     ...
         
     | 
| 
      
 90 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 91 
     | 
    
         
            +
                #
         
     | 
| 
      
 92 
     | 
    
         
            +
                # @param [ Mongo::Session ] session The session that the operation is being
         
     | 
| 
      
 93 
     | 
    
         
            +
                #   run on.
         
     | 
| 
      
 94 
     | 
    
         
            +
                # @param [ Mongo::ServerSelector::Selectable ] server_selector Server
         
     | 
| 
      
 95 
     | 
    
         
            +
                #   selector for the operation.
         
     | 
| 
       34 
96 
     | 
    
         
             
                # @param [ Proc ] block The block to execute.
         
     | 
| 
       35 
97 
     | 
    
         
             
                #
         
     | 
| 
       36 
98 
     | 
    
         
             
                # @return [ Result ] The result of the operation.
         
     | 
| 
       37 
     | 
    
         
            -
                 
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
                      raise
         
     | 
| 
       47 
     | 
    
         
            -
                    end
         
     | 
| 
       48 
     | 
    
         
            -
                    log_retry(e)
         
     | 
| 
       49 
     | 
    
         
            -
                    cluster.scan!(false)
         
     | 
| 
       50 
     | 
    
         
            -
                    retry
         
     | 
| 
       51 
     | 
    
         
            -
                  rescue Error::OperationFailure => e
         
     | 
| 
       52 
     | 
    
         
            -
                    if cluster.sharded? && e.retryable? && !(session && session.in_transaction?)
         
     | 
| 
       53 
     | 
    
         
            -
                      if attempt > cluster.max_read_retries
         
     | 
| 
       54 
     | 
    
         
            -
                        raise
         
     | 
| 
       55 
     | 
    
         
            -
                      end
         
     | 
| 
       56 
     | 
    
         
            -
                      log_retry(e)
         
     | 
| 
       57 
     | 
    
         
            -
                      sleep(cluster.read_retry_interval)
         
     | 
| 
       58 
     | 
    
         
            -
                      retry
         
     | 
| 
       59 
     | 
    
         
            -
                    else
         
     | 
| 
       60 
     | 
    
         
            -
                      raise
         
     | 
| 
      
 99 
     | 
    
         
            +
                def read_with_retry(session = nil, server_selector = nil, &block)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  if session.nil? && server_selector.nil?
         
     | 
| 
      
 101 
     | 
    
         
            +
                    # Older versions of Mongoid call read_with_retry without arguments.
         
     | 
| 
      
 102 
     | 
    
         
            +
                    # This is already not correct in a MongoDB 3.6+ environment with
         
     | 
| 
      
 103 
     | 
    
         
            +
                    # sessions. For compatibility we emulate the legacy driver behavior
         
     | 
| 
      
 104 
     | 
    
         
            +
                    # here but upgrading Mongoid is strongly recommended.
         
     | 
| 
      
 105 
     | 
    
         
            +
                    unless $_mongo_read_with_retry_warned
         
     | 
| 
      
 106 
     | 
    
         
            +
                      $_mongo_read_with_retry_warned = true
         
     | 
| 
      
 107 
     | 
    
         
            +
                      Logger.logger.warn("Legacy read_with_retry invocation - please update the application and/or its dependencies")
         
     | 
| 
       61 
108 
     | 
    
         
             
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
                    # Since we don't have a session, we cannot use the modern read retries.
         
     | 
| 
      
 110 
     | 
    
         
            +
                    # And we need to select a server but we don't have a server selector.
         
     | 
| 
      
 111 
     | 
    
         
            +
                    # Use PrimaryPreferred which will work as long as there is a data
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # bearing node in the cluster; the block may select a different server
         
     | 
| 
      
 113 
     | 
    
         
            +
                    # which is fine.
         
     | 
| 
      
 114 
     | 
    
         
            +
                    server_selector = ServerSelector.get(mode: :primary_preferred)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    legacy_read_with_retry(nil, server_selector, &block)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  elsif session && session.retry_reads?
         
     | 
| 
      
 117 
     | 
    
         
            +
                    modern_read_with_retry(session, server_selector, &block)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  elsif client.max_read_retries > 0
         
     | 
| 
      
 119 
     | 
    
         
            +
                    legacy_read_with_retry(session, server_selector, &block)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  else
         
     | 
| 
      
 121 
     | 
    
         
            +
                    server = select_server(cluster, server_selector)
         
     | 
| 
      
 122 
     | 
    
         
            +
                    yield server
         
     | 
| 
       62 
123 
     | 
    
         
             
                  end
         
     | 
| 
       63 
124 
     | 
    
         
             
                end
         
     | 
| 
       64 
125 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                # Execute a read operation with a single retry.
         
     | 
| 
      
 126 
     | 
    
         
            +
                # Execute a read operation with a single retry on network errors.
         
     | 
| 
      
 127 
     | 
    
         
            +
                #
         
     | 
| 
      
 128 
     | 
    
         
            +
                # This method is used by the driver for some of the internal housekeeping
         
     | 
| 
      
 129 
     | 
    
         
            +
                # operations. Application-requested reads should use read_with_retry
         
     | 
| 
      
 130 
     | 
    
         
            +
                # rather than this method.
         
     | 
| 
       66 
131 
     | 
    
         
             
                #
         
     | 
| 
       67 
132 
     | 
    
         
             
                # @api private
         
     | 
| 
       68 
133 
     | 
    
         
             
                #
         
     | 
| 
         @@ -159,6 +224,52 @@ module Mongo 
     | 
|
| 
       159 
224 
     | 
    
         | 
| 
       160 
225 
     | 
    
         
             
                private
         
     | 
| 
       161 
226 
     | 
    
         | 
| 
      
 227 
     | 
    
         
            +
                def modern_read_with_retry(session, server_selector, &block)
         
     | 
| 
      
 228 
     | 
    
         
            +
                  attempt = 0
         
     | 
| 
      
 229 
     | 
    
         
            +
                  server = select_server(cluster, server_selector)
         
     | 
| 
      
 230 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 231 
     | 
    
         
            +
                    yield server
         
     | 
| 
      
 232 
     | 
    
         
            +
                  rescue Error::SocketError, Error::SocketTimeoutError => e
         
     | 
| 
      
 233 
     | 
    
         
            +
                    if session.in_transaction?
         
     | 
| 
      
 234 
     | 
    
         
            +
                      raise
         
     | 
| 
      
 235 
     | 
    
         
            +
                    end
         
     | 
| 
      
 236 
     | 
    
         
            +
                    retry_read(e, server_selector, &block)
         
     | 
| 
      
 237 
     | 
    
         
            +
                  rescue Error::OperationFailure => e
         
     | 
| 
      
 238 
     | 
    
         
            +
                    if session.in_transaction? || !e.write_retryable?
         
     | 
| 
      
 239 
     | 
    
         
            +
                      raise
         
     | 
| 
      
 240 
     | 
    
         
            +
                    end
         
     | 
| 
      
 241 
     | 
    
         
            +
                    retry_read(e, server_selector, &block)
         
     | 
| 
      
 242 
     | 
    
         
            +
                  end
         
     | 
| 
      
 243 
     | 
    
         
            +
                end
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
                def legacy_read_with_retry(session, server_selector)
         
     | 
| 
      
 246 
     | 
    
         
            +
                  attempt = 0
         
     | 
| 
      
 247 
     | 
    
         
            +
                  server = select_server(cluster, server_selector)
         
     | 
| 
      
 248 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 249 
     | 
    
         
            +
                    attempt += 1
         
     | 
| 
      
 250 
     | 
    
         
            +
                    yield server
         
     | 
| 
      
 251 
     | 
    
         
            +
                  rescue Error::SocketError, Error::SocketTimeoutError => e
         
     | 
| 
      
 252 
     | 
    
         
            +
                    if attempt > client.max_read_retries || (session && session.in_transaction?)
         
     | 
| 
      
 253 
     | 
    
         
            +
                      raise
         
     | 
| 
      
 254 
     | 
    
         
            +
                    end
         
     | 
| 
      
 255 
     | 
    
         
            +
                    log_retry(e, message: 'Legacy read retry')
         
     | 
| 
      
 256 
     | 
    
         
            +
                    server = select_server(cluster, server_selector)
         
     | 
| 
      
 257 
     | 
    
         
            +
                    retry
         
     | 
| 
      
 258 
     | 
    
         
            +
                  rescue Error::OperationFailure => e
         
     | 
| 
      
 259 
     | 
    
         
            +
                    if cluster.sharded? && e.retryable? && !(session && session.in_transaction?)
         
     | 
| 
      
 260 
     | 
    
         
            +
                      if attempt > client.max_read_retries
         
     | 
| 
      
 261 
     | 
    
         
            +
                        raise
         
     | 
| 
      
 262 
     | 
    
         
            +
                      end
         
     | 
| 
      
 263 
     | 
    
         
            +
                      log_retry(e, message: 'Legacy read retry')
         
     | 
| 
      
 264 
     | 
    
         
            +
                      sleep(client.read_retry_interval)
         
     | 
| 
      
 265 
     | 
    
         
            +
                      server = select_server(cluster, server_selector)
         
     | 
| 
      
 266 
     | 
    
         
            +
                      retry
         
     | 
| 
      
 267 
     | 
    
         
            +
                    else
         
     | 
| 
      
 268 
     | 
    
         
            +
                      raise
         
     | 
| 
      
 269 
     | 
    
         
            +
                    end
         
     | 
| 
      
 270 
     | 
    
         
            +
                  end
         
     | 
| 
      
 271 
     | 
    
         
            +
                end
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
       162 
273 
     | 
    
         
             
                def retry_write_allowed?(session, write_concern)
         
     | 
| 
       163 
274 
     | 
    
         
             
                  unless session && session.retry_writes?
         
     | 
| 
       164 
275 
     | 
    
         
             
                    return false
         
     | 
| 
         @@ -174,6 +285,27 @@ module Mongo 
     | 
|
| 
       174 
285 
     | 
    
         
             
                  end
         
     | 
| 
       175 
286 
     | 
    
         
             
                end
         
     | 
| 
       176 
287 
     | 
    
         | 
| 
      
 288 
     | 
    
         
            +
                def retry_read(original_error, server_selector, &block)
         
     | 
| 
      
 289 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 290 
     | 
    
         
            +
                    server = select_server(cluster, server_selector)
         
     | 
| 
      
 291 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 292 
     | 
    
         
            +
                    raise original_error
         
     | 
| 
      
 293 
     | 
    
         
            +
                  end
         
     | 
| 
      
 294 
     | 
    
         
            +
             
     | 
| 
      
 295 
     | 
    
         
            +
                  log_retry(original_error, message: 'Read retry')
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 298 
     | 
    
         
            +
                    yield server, true
         
     | 
| 
      
 299 
     | 
    
         
            +
                  rescue Error::SocketError, Error::SocketTimeoutError => e
         
     | 
| 
      
 300 
     | 
    
         
            +
                    raise e
         
     | 
| 
      
 301 
     | 
    
         
            +
                  rescue Error::OperationFailure => e
         
     | 
| 
      
 302 
     | 
    
         
            +
                    raise original_error unless e.write_retryable?
         
     | 
| 
      
 303 
     | 
    
         
            +
                    raise e
         
     | 
| 
      
 304 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 305 
     | 
    
         
            +
                    raise original_error
         
     | 
| 
      
 306 
     | 
    
         
            +
                  end
         
     | 
| 
      
 307 
     | 
    
         
            +
                end
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
       177 
309 
     | 
    
         
             
                def retry_write(original_error, txn_num, &block)
         
     | 
| 
       178 
310 
     | 
    
         
             
                  # We do not request a scan of the cluster here, because error handling
         
     | 
| 
       179 
311 
     | 
    
         
             
                  # for the error which triggered the retry should have updated the
         
     | 
| 
         @@ -182,7 +314,7 @@ module Mongo 
     | 
|
| 
       182 
314 
     | 
    
         
             
                  # server unknown). Here we just need to wait for server selection.
         
     | 
| 
       183 
315 
     | 
    
         
             
                  server = cluster.next_primary
         
     | 
| 
       184 
316 
     | 
    
         
             
                  raise original_error unless (server.retry_writes? && txn_num)
         
     | 
| 
       185 
     | 
    
         
            -
                  log_retry(original_error)
         
     | 
| 
      
 317 
     | 
    
         
            +
                  log_retry(original_error, message: 'Write retry')
         
     | 
| 
       186 
318 
     | 
    
         
             
                  yield(server, txn_num, true)
         
     | 
| 
       187 
319 
     | 
    
         
             
                rescue Error::SocketError, Error::SocketTimeoutError => e
         
     | 
| 
       188 
320 
     | 
    
         
             
                  raise e
         
     | 
| 
         @@ -203,11 +335,11 @@ module Mongo 
     | 
|
| 
       203 
335 
     | 
    
         
             
                    yield(server || cluster.next_primary)
         
     | 
| 
       204 
336 
     | 
    
         
             
                  rescue Error::OperationFailure => e
         
     | 
| 
       205 
337 
     | 
    
         
             
                    server = nil
         
     | 
| 
       206 
     | 
    
         
            -
                    if attempt >  
     | 
| 
      
 338 
     | 
    
         
            +
                    if attempt > client.max_write_retries
         
     | 
| 
       207 
339 
     | 
    
         
             
                      raise
         
     | 
| 
       208 
340 
     | 
    
         
             
                    end
         
     | 
| 
       209 
341 
     | 
    
         
             
                    if e.write_retryable? && !(session && session.in_transaction?)
         
     | 
| 
       210 
     | 
    
         
            -
                      log_retry(e)
         
     | 
| 
      
 342 
     | 
    
         
            +
                      log_retry(e, message: 'Legacy write retry')
         
     | 
| 
       211 
343 
     | 
    
         
             
                      cluster.scan!(false)
         
     | 
| 
       212 
344 
     | 
    
         
             
                      retry
         
     | 
| 
       213 
345 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -216,6 +348,12 @@ module Mongo 
     | 
|
| 
       216 
348 
     | 
    
         
             
                  end
         
     | 
| 
       217 
349 
     | 
    
         
             
                end
         
     | 
| 
       218 
350 
     | 
    
         | 
| 
      
 351 
     | 
    
         
            +
                # This is a separate method to make it possible for the test suite to
         
     | 
| 
      
 352 
     | 
    
         
            +
                # assert that server selection is performed during retry attempts.
         
     | 
| 
      
 353 
     | 
    
         
            +
                def select_server(cluster, server_selector)
         
     | 
| 
      
 354 
     | 
    
         
            +
                  server_selector.select_server(cluster)
         
     | 
| 
      
 355 
     | 
    
         
            +
                end
         
     | 
| 
      
 356 
     | 
    
         
            +
             
     | 
| 
       219 
357 
     | 
    
         
             
                # Log a warning so that any application slow down is immediately obvious.
         
     | 
| 
       220 
358 
     | 
    
         
             
                def log_retry(e, options = nil)
         
     | 
| 
       221 
359 
     | 
    
         
             
                  message = if options && options[:message]
         
     | 
    
        data/lib/mongo/server.rb
    CHANGED
    
    | 
         @@ -61,6 +61,9 @@ module Mongo 
     | 
|
| 
       61 
61 
     | 
    
         
             
                  monitor = options.delete(:monitor)
         
     | 
| 
       62 
62 
     | 
    
         
             
                  @options = options.freeze
         
     | 
| 
       63 
63 
     | 
    
         
             
                  @event_listeners = event_listeners
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @connection_id_gen = Class.new do
         
     | 
| 
      
 65 
     | 
    
         
            +
                    include Id
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
       64 
67 
     | 
    
         
             
                  @monitor = Monitor.new(address, event_listeners, monitoring,
         
     | 
| 
       65 
68 
     | 
    
         
             
                    options.merge(app_metadata: Monitor::AppMetadata.new(cluster.options)))
         
     | 
| 
       66 
69 
     | 
    
         
             
                  unless monitor == false
         
     | 
| 
         @@ -178,7 +181,13 @@ module Mongo 
     | 
|
| 
       178 
181 
     | 
    
         
             
                #
         
     | 
| 
       179 
182 
     | 
    
         
             
                # @since 2.0.0
         
     | 
| 
       180 
183 
     | 
    
         
             
                def disconnect!(wait=false)
         
     | 
| 
       181 
     | 
    
         
            -
                   
     | 
| 
      
 184 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 185 
     | 
    
         
            +
                    # For backwards compatibility we disconnect/clear the pool rather
         
     | 
| 
      
 186 
     | 
    
         
            +
                    # than close it here.
         
     | 
| 
      
 187 
     | 
    
         
            +
                    pool.disconnect!
         
     | 
| 
      
 188 
     | 
    
         
            +
                  rescue Error::PoolClosedError
         
     | 
| 
      
 189 
     | 
    
         
            +
                    # If the pool was already closed, we don't need to do anything here.
         
     | 
| 
      
 190 
     | 
    
         
            +
                  end
         
     | 
| 
       182 
191 
     | 
    
         
             
                  monitor.stop!(wait)
         
     | 
| 
       183 
192 
     | 
    
         
             
                  @connected = false
         
     | 
| 
       184 
193 
     | 
    
         
             
                  true
         
     | 
| 
         @@ -282,11 +291,7 @@ module Mongo 
     | 
|
| 
       282 
291 
     | 
    
         
             
                # @since 2.0.0
         
     | 
| 
       283 
292 
     | 
    
         
             
                def pool
         
     | 
| 
       284 
293 
     | 
    
         
             
                  @pool_lock.synchronize do
         
     | 
| 
       285 
     | 
    
         
            -
                    @pool ||=  
     | 
| 
       286 
     | 
    
         
            -
                      ConnectionPool.new(options) do |generation|
         
     | 
| 
       287 
     | 
    
         
            -
                        Connection.new(self, options.merge(generation: generation))
         
     | 
| 
       288 
     | 
    
         
            -
                      end
         
     | 
| 
       289 
     | 
    
         
            -
                    end
         
     | 
| 
      
 294 
     | 
    
         
            +
                    @pool ||= ConnectionPool.new(self, options)
         
     | 
| 
       290 
295 
     | 
    
         
             
                  end
         
     | 
| 
       291 
296 
     | 
    
         
             
                end
         
     | 
| 
       292 
297 
     | 
    
         | 
| 
         @@ -315,7 +320,9 @@ module Mongo 
     | 
|
| 
       315 
320 
     | 
    
         
             
                #
         
     | 
| 
       316 
321 
     | 
    
         
             
                # @since 2.1.0
         
     | 
| 
       317 
322 
     | 
    
         
             
                def reconnect!
         
     | 
| 
       318 
     | 
    
         
            -
                   
     | 
| 
      
 323 
     | 
    
         
            +
                  if options[:monitoring_io] != false
         
     | 
| 
      
 324 
     | 
    
         
            +
                    monitor.restart!
         
     | 
| 
      
 325 
     | 
    
         
            +
                  end
         
     | 
| 
       319 
326 
     | 
    
         
             
                  @connected = true
         
     | 
| 
       320 
327 
     | 
    
         
             
                end
         
     | 
| 
       321 
328 
     | 
    
         | 
| 
         @@ -373,6 +380,13 @@ module Mongo 
     | 
|
| 
       373 
380 
     | 
    
         
             
                  raise
         
     | 
| 
       374 
381 
     | 
    
         
             
                end
         
     | 
| 
       375 
382 
     | 
    
         | 
| 
      
 383 
     | 
    
         
            +
                # Whether the server supports modern read retries.
         
     | 
| 
      
 384 
     | 
    
         
            +
                #
         
     | 
| 
      
 385 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 386 
     | 
    
         
            +
                def retry_reads?
         
     | 
| 
      
 387 
     | 
    
         
            +
                  !!(features.sessions_enabled? && logical_session_timeout)
         
     | 
| 
      
 388 
     | 
    
         
            +
                end
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
       376 
390 
     | 
    
         
             
                # Will writes sent to this server be retried.
         
     | 
| 
       377 
391 
     | 
    
         
             
                #
         
     | 
| 
       378 
392 
     | 
    
         
             
                # @example Will writes be retried.
         
     | 
| 
         @@ -403,6 +417,11 @@ module Mongo 
     | 
|
| 
       403 
417 
     | 
    
         
             
                def update_description(description)
         
     | 
| 
       404 
418 
     | 
    
         
             
                  monitor.instance_variable_set('@description', description)
         
     | 
| 
       405 
419 
     | 
    
         
             
                end
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
      
 421 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 422 
     | 
    
         
            +
                def next_connection_id
         
     | 
| 
      
 423 
     | 
    
         
            +
                  @connection_id_gen.next_id
         
     | 
| 
      
 424 
     | 
    
         
            +
                end
         
     | 
| 
       406 
425 
     | 
    
         
             
              end
         
     | 
| 
       407 
426 
     | 
    
         
             
            end
         
     | 
| 
       408 
427 
     | 
    
         | 
| 
         @@ -81,15 +81,21 @@ module Mongo 
     | 
|
| 
       81 
81 
     | 
    
         
             
                      result
         
     | 
| 
       82 
82 
     | 
    
         
             
                    ensure
         
     | 
| 
       83 
83 
     | 
    
         
             
                      unless success
         
     | 
| 
       84 
     | 
    
         
            -
                        disconnect!
         
     | 
| 
      
 84 
     | 
    
         
            +
                        disconnect!(reason: :error)
         
     | 
| 
       85 
85 
     | 
    
         
             
                      end
         
     | 
| 
       86 
86 
     | 
    
         
             
                    end
         
     | 
| 
       87 
87 
     | 
    
         
             
                  end
         
     | 
| 
       88 
88 
     | 
    
         | 
| 
       89 
89 
     | 
    
         
             
                  def ensure_same_process!
         
     | 
| 
       90 
90 
     | 
    
         
             
                    if pid != Process.pid
         
     | 
| 
       91 
     | 
    
         
            -
                       
     | 
| 
      
 91 
     | 
    
         
            +
                      # When we reconnect here, CMAP events won't be correctly sent
         
     | 
| 
      
 92 
     | 
    
         
            +
                      # since the CMAP spec does not permit a connection to be disconnected
         
     | 
| 
      
 93 
     | 
    
         
            +
                      # and then reconnected
         
     | 
| 
      
 94 
     | 
    
         
            +
                      log_warn("Detected PID change - Mongo client should have been reconnected (old pid #{pid}, new pid #{Process.pid}")
         
     | 
| 
      
 95 
     | 
    
         
            +
                      disconnect!(reason: :stale)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      @closed = false
         
     | 
| 
       92 
97 
     | 
    
         
             
                      @pid = Process.pid
         
     | 
| 
      
 98 
     | 
    
         
            +
                      connect!
         
     | 
| 
       93 
99 
     | 
    
         
             
                    end
         
     | 
| 
       94 
100 
     | 
    
         
             
                  end
         
     | 
| 
       95 
101 
     | 
    
         
             
                end
         
     | 
| 
         @@ -89,6 +89,7 @@ module Mongo 
     | 
|
| 
       89 
89 
     | 
    
         
             
                  #
         
     | 
| 
       90 
90 
     | 
    
         
             
                  # @since 2.0.0
         
     | 
| 
       91 
91 
     | 
    
         
             
                  def initialize(server, options = {})
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @id = server.next_connection_id
         
     | 
| 
       92 
93 
     | 
    
         
             
                    @monitoring = server.monitoring
         
     | 
| 
       93 
94 
     | 
    
         
             
                    @options = options.freeze
         
     | 
| 
       94 
95 
     | 
    
         
             
                    @server = server
         
     | 
| 
         @@ -97,13 +98,23 @@ module Mongo 
     | 
|
| 
       97 
98 
     | 
    
         
             
                    @last_checkin = nil
         
     | 
| 
       98 
99 
     | 
    
         
             
                    @auth_mechanism = nil
         
     | 
| 
       99 
100 
     | 
    
         
             
                    @pid = Process.pid
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    publish_cmap_event(
         
     | 
| 
      
 103 
     | 
    
         
            +
                      Monitoring::Event::Cmap::ConnectionCreated.new(address, id)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    )
         
     | 
| 
       100 
105 
     | 
    
         
             
                  end
         
     | 
| 
       101 
106 
     | 
    
         | 
| 
       102 
     | 
    
         
            -
                  # The last time the connection was checked back into a pool.
         
     | 
| 
      
 107 
     | 
    
         
            +
                  # @return [ Time ] The last time the connection was checked back into a pool.
         
     | 
| 
       103 
108 
     | 
    
         
             
                  #
         
     | 
| 
       104 
109 
     | 
    
         
             
                  # @since 2.5.0
         
     | 
| 
       105 
110 
     | 
    
         
             
                  attr_reader :last_checkin
         
     | 
| 
       106 
111 
     | 
    
         | 
| 
      
 112 
     | 
    
         
            +
                  # @return [ Integer ] The ID for the connection. This will be unique
         
     | 
| 
      
 113 
     | 
    
         
            +
                  # across connections to the same server object.
         
     | 
| 
      
 114 
     | 
    
         
            +
                  #
         
     | 
| 
      
 115 
     | 
    
         
            +
                  # @since 2.9.0
         
     | 
| 
      
 116 
     | 
    
         
            +
                  attr_reader :id
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       107 
118 
     | 
    
         
             
                  # Connection pool generation from which this connection was created.
         
     | 
| 
       108 
119 
     | 
    
         
             
                  # May be nil.
         
     | 
| 
       109 
120 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -113,6 +124,18 @@ module Mongo 
     | 
|
| 
       113 
124 
     | 
    
         
             
                    options[:generation]
         
     | 
| 
       114 
125 
     | 
    
         
             
                  end
         
     | 
| 
       115 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
                  # Whether the connection was closed.
         
     | 
| 
      
 128 
     | 
    
         
            +
                  #
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # Closed connections should no longer be used. Instead obtain a new
         
     | 
| 
      
 130 
     | 
    
         
            +
                  # connection from the connection pool.
         
     | 
| 
      
 131 
     | 
    
         
            +
                  #
         
     | 
| 
      
 132 
     | 
    
         
            +
                  # @return [ true | false ] Whether connection was closed.
         
     | 
| 
      
 133 
     | 
    
         
            +
                  #
         
     | 
| 
      
 134 
     | 
    
         
            +
                  # @since 2.9.0
         
     | 
| 
      
 135 
     | 
    
         
            +
                  def closed?
         
     | 
| 
      
 136 
     | 
    
         
            +
                    !!@closed
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
       116 
139 
     | 
    
         
             
                  # Establishes a network connection to the target address.
         
     | 
| 
       117 
140 
     | 
    
         
             
                  #
         
     | 
| 
       118 
141 
     | 
    
         
             
                  # If the connection is already established, this method does nothing.
         
     | 
| 
         @@ -120,44 +143,91 @@ module Mongo 
     | 
|
| 
       120 
143 
     | 
    
         
             
                  # @example Connect to the host.
         
     | 
| 
       121 
144 
     | 
    
         
             
                  #   connection.connect!
         
     | 
| 
       122 
145 
     | 
    
         
             
                  #
         
     | 
| 
       123 
     | 
    
         
            -
                  # @note This method mutates the connection  
     | 
| 
      
 146 
     | 
    
         
            +
                  # @note This method mutates the connection object by setting a socket if
         
     | 
| 
       124 
147 
     | 
    
         
             
                  #   one previously did not exist.
         
     | 
| 
       125 
148 
     | 
    
         
             
                  #
         
     | 
| 
       126 
149 
     | 
    
         
             
                  # @return [ true ] If the connection succeeded.
         
     | 
| 
       127 
150 
     | 
    
         
             
                  #
         
     | 
| 
       128 
151 
     | 
    
         
             
                  # @since 2.0.0
         
     | 
| 
       129 
152 
     | 
    
         
             
                  def connect!
         
     | 
| 
      
 153 
     | 
    
         
            +
                    if closed?
         
     | 
| 
      
 154 
     | 
    
         
            +
                      if Lint.enabled?
         
     | 
| 
      
 155 
     | 
    
         
            +
                        raise Error::LintError, "Reconnecting closed connections is no longer supported"
         
     | 
| 
      
 156 
     | 
    
         
            +
                      else
         
     | 
| 
      
 157 
     | 
    
         
            +
                        log_warn("Reconnecting closed connections is deprecated (for #{address})")
         
     | 
| 
      
 158 
     | 
    
         
            +
                      end
         
     | 
| 
      
 159 
     | 
    
         
            +
                    end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
       130 
161 
     | 
    
         
             
                    unless @socket
         
     | 
| 
       131 
     | 
    
         
            -
                      socket = address.socket(socket_timeout, ssl_options,
         
     | 
| 
       132 
     | 
    
         
            -
                        connect_timeout: address.connect_timeout)
         
     | 
| 
       133 
     | 
    
         
            -
                      handshake!(socket)
         
     | 
| 
       134 
     | 
    
         
            -
                      pending_connection = PendingConnection.new(socket, @server, monitoring, options)
         
     | 
| 
       135 
     | 
    
         
            -
                      authenticate!(pending_connection)
         
     | 
| 
       136 
162 
     | 
    
         
             
                      # When @socket is assigned, the socket should have handshaken and
         
     | 
| 
       137 
163 
     | 
    
         
             
                      # authenticated and be usable.
         
     | 
| 
       138 
     | 
    
         
            -
                      @socket =  
     | 
| 
      
 164 
     | 
    
         
            +
                      @socket = do_connect
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                      publish_cmap_event(
         
     | 
| 
      
 167 
     | 
    
         
            +
                        Monitoring::Event::Cmap::ConnectionReady.new(address, id)
         
     | 
| 
      
 168 
     | 
    
         
            +
                      )
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                      @close_event_published = false
         
     | 
| 
       139 
171 
     | 
    
         
             
                    end
         
     | 
| 
       140 
172 
     | 
    
         
             
                    true
         
     | 
| 
       141 
173 
     | 
    
         
             
                  end
         
     | 
| 
       142 
174 
     | 
    
         | 
| 
      
 175 
     | 
    
         
            +
                  # Separate method to permit easier mocking in the test suite.
         
     | 
| 
      
 176 
     | 
    
         
            +
                  def do_connect
         
     | 
| 
      
 177 
     | 
    
         
            +
                    socket = address.socket(socket_timeout, ssl_options,
         
     | 
| 
      
 178 
     | 
    
         
            +
                      connect_timeout: address.connect_timeout)
         
     | 
| 
      
 179 
     | 
    
         
            +
                    handshake!(socket)
         
     | 
| 
      
 180 
     | 
    
         
            +
                    pending_connection = PendingConnection.new(socket, @server, monitoring, options)
         
     | 
| 
      
 181 
     | 
    
         
            +
                    authenticate!(pending_connection)
         
     | 
| 
      
 182 
     | 
    
         
            +
                    socket
         
     | 
| 
      
 183 
     | 
    
         
            +
                  end
         
     | 
| 
      
 184 
     | 
    
         
            +
                  private :do_connect
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
       143 
186 
     | 
    
         
             
                  # Disconnect the connection.
         
     | 
| 
       144 
187 
     | 
    
         
             
                  #
         
     | 
| 
       145 
     | 
    
         
            -
                  # @ 
     | 
| 
       146 
     | 
    
         
            -
                  #   connection 
     | 
| 
      
 188 
     | 
    
         
            +
                  # @note Once a connection is disconnected, it should no longer be used.
         
     | 
| 
      
 189 
     | 
    
         
            +
                  #   A new connection should be obtained from the connection pool which
         
     | 
| 
      
 190 
     | 
    
         
            +
                  #   will either return a ready connection or create a new connection.
         
     | 
| 
      
 191 
     | 
    
         
            +
                  #   If linting is enabled, reusing a disconnected connection will raise
         
     | 
| 
      
 192 
     | 
    
         
            +
                  #   Error::LintError. If linting is not enabled, a warning will be logged.
         
     | 
| 
      
 193 
     | 
    
         
            +
                  #
         
     | 
| 
      
 194 
     | 
    
         
            +
                  # @note This method mutates the connection object by setting the socket
         
     | 
| 
      
 195 
     | 
    
         
            +
                  #   to nil if the closing succeeded.
         
     | 
| 
       147 
196 
     | 
    
         
             
                  #
         
     | 
| 
       148 
     | 
    
         
            -
                  # @ 
     | 
| 
       149 
     | 
    
         
            -
                  #    
     | 
| 
      
 197 
     | 
    
         
            +
                  # @option options [ Symbol ] :reason The reason why the connection is
         
     | 
| 
      
 198 
     | 
    
         
            +
                  #   being closed.
         
     | 
| 
       150 
199 
     | 
    
         
             
                  #
         
     | 
| 
       151 
200 
     | 
    
         
             
                  # @return [ true ] If the disconnect succeeded.
         
     | 
| 
       152 
201 
     | 
    
         
             
                  #
         
     | 
| 
       153 
202 
     | 
    
         
             
                  # @since 2.0.0
         
     | 
| 
       154 
     | 
    
         
            -
                  def disconnect!
         
     | 
| 
      
 203 
     | 
    
         
            +
                  def disconnect!(options = nil)
         
     | 
| 
      
 204 
     | 
    
         
            +
                    # Note: @closed may be true here but we also may have a socket.
         
     | 
| 
      
 205 
     | 
    
         
            +
                    # Check the socket and not @closed flag.
         
     | 
| 
       155 
206 
     | 
    
         
             
                    @auth_mechanism = nil
         
     | 
| 
       156 
207 
     | 
    
         
             
                    @last_checkin = nil
         
     | 
| 
       157 
208 
     | 
    
         
             
                    if socket
         
     | 
| 
       158 
209 
     | 
    
         
             
                      socket.close
         
     | 
| 
       159 
210 
     | 
    
         
             
                      @socket = nil
         
     | 
| 
       160 
211 
     | 
    
         
             
                    end
         
     | 
| 
      
 212 
     | 
    
         
            +
                    @closed = true
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                    # To satisfy CMAP spec tests, publish close events even if the
         
     | 
| 
      
 215 
     | 
    
         
            +
                    # socket was never connected (and thus the ready event was never
         
     | 
| 
      
 216 
     | 
    
         
            +
                    # published). But track whether we published close event and do not
         
     | 
| 
      
 217 
     | 
    
         
            +
                    # publish it multiple times, unless the socket was reconnected -
         
     | 
| 
      
 218 
     | 
    
         
            +
                    # in that case publish the close event once per socket close.
         
     | 
| 
      
 219 
     | 
    
         
            +
                    unless @close_event_published
         
     | 
| 
      
 220 
     | 
    
         
            +
                      reason = options && options[:reason]
         
     | 
| 
      
 221 
     | 
    
         
            +
                      publish_cmap_event(
         
     | 
| 
      
 222 
     | 
    
         
            +
                        Monitoring::Event::Cmap::ConnectionClosed.new(
         
     | 
| 
      
 223 
     | 
    
         
            +
                          address,
         
     | 
| 
      
 224 
     | 
    
         
            +
                          id,
         
     | 
| 
      
 225 
     | 
    
         
            +
                          reason,
         
     | 
| 
      
 226 
     | 
    
         
            +
                        ),
         
     | 
| 
      
 227 
     | 
    
         
            +
                      )
         
     | 
| 
      
 228 
     | 
    
         
            +
                      @close_event_published = true
         
     | 
| 
      
 229 
     | 
    
         
            +
                    end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
       161 
231 
     | 
    
         
             
                    true
         
     | 
| 
       162 
232 
     | 
    
         
             
                  end
         
     | 
| 
       163 
233 
     | 
    
         |