mongo_ha 1.12.0 → 1.12.1
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
- data/README.md +1 -1
- data/lib/mongo_ha.rb +5 -7
- data/lib/mongo_ha/mongo_client.rb +25 -39
- data/lib/mongo_ha/version.rb +1 -1
- data/test/readme.md +48 -0
- metadata +8 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 24001e509a2bf4c267e910c0086d4600092aeeff
         | 
| 4 | 
            +
              data.tar.gz: 4af9185eaf2cdcad47e53786c4c27776702734c7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 4eb4feae513d86c118d01b00d0e274a9668d551f83e456ea9abf946d05080800d0fddb1c20faa62dde4aa7d8b012dd845268c5d2aa8c60670aba31a442f6efbb
         | 
| 7 | 
            +
              data.tar.gz: 0cd992c13c58cd09b7f32168c21189ef86456a4bba5546ebbae1530a0879d4954b6a8e9c9315f294b3dd742e59defe346b2bbb80c596f3e65b4b357a4bee1f07
         | 
    
        data/README.md
    CHANGED
    
    | @@ -153,7 +153,7 @@ Using the above default values, will result in retry connects at the following i | |
| 153 153 |  | 
| 154 154 | 
             
            There is really only one place to test something like `mongo_ha` and that is in
         | 
| 155 155 | 
             
            a high volume mission critical production environment.
         | 
| 156 | 
            -
             | 
| 156 | 
            +
            This gem was created and tested with MongoDB running in an
         | 
| 157 157 | 
             
            enterprise production environment with hundreds of connections to Mongo servers
         | 
| 158 158 | 
             
            in remote data centers across a WAN. It adds high availability to standalone
         | 
| 159 159 | 
             
            MongoDB servers, replica-sets, and sharded clusters.
         | 
    
        data/lib/mongo_ha.rb
    CHANGED
    
    | @@ -7,14 +7,12 @@ Mongo::MongoClient.send(:include, MongoHA::MongoClient::InstanceMethods) | |
| 7 7 |  | 
| 8 8 | 
             
            # Wrap critical Mongo methods with retry_on_connection_failure
         | 
| 9 9 | 
             
            {
         | 
| 10 | 
            -
               | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                :options, :stats, :map_reduce
         | 
| 14 | 
            -
              ],
         | 
| 15 | 
            -
              Mongo::CollectionOperationWriter => [:send_write_operation, :batch_message_send],
         | 
| 16 | 
            -
              Mongo::CollectionCommandWriter   => [:send_write_command, :batch_message_send]
         | 
| 10 | 
            +
              # Most calls use a cursor under the covers to return the result
         | 
| 11 | 
            +
              # If the primary is lost and it connects to a different server an expired cursor exception is raised
         | 
| 12 | 
            +
              Mongo::Cursor     => [:refresh],
         | 
| 17 13 |  | 
| 14 | 
            +
              # These methods do not use a Cursor
         | 
| 15 | 
            +
              Mongo::Collection => [:insert, :remove, :update]
         | 
| 18 16 | 
             
            }.each_pair do |klass, methods|
         | 
| 19 17 | 
             
              methods.each do |method|
         | 
| 20 18 | 
             
                original_method = "#{method}_original".to_sym
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            require 'mongo'
         | 
| 2 2 | 
             
            module MongoHA
         | 
| 3 3 | 
             
              module MongoClient
         | 
| 4 | 
            -
                CONNECTION_RETRY_OPTS | 
| 4 | 
            +
                CONNECTION_RETRY_OPTS    = [:reconnect_attempts, :reconnect_retry_seconds, :reconnect_retry_multiplier, :reconnect_max_retry_seconds]
         | 
| 5 5 |  | 
| 6 6 | 
             
                # The following errors occur when mongos cannot connect to the shard
         | 
| 7 7 | 
             
                # They require a retry to resolve them
         | 
| @@ -50,8 +50,6 @@ module MongoHA | |
| 50 50 | 
             
                        end
         | 
| 51 51 | 
             
                      end
         | 
| 52 52 |  | 
| 53 | 
            -
                      alias_method :receive_message_original, :receive_message
         | 
| 54 | 
            -
                      alias_method :connect_original, :connect
         | 
| 55 53 | 
             
                      alias_method :valid_opts_original, :valid_opts
         | 
| 56 54 | 
             
                      alias_method :setup_original, :setup
         | 
| 57 55 |  | 
| @@ -60,22 +58,6 @@ module MongoHA | |
| 60 58 | 
             
                      # Prevent multiple threads from trying to reconnect at the same time during
         | 
| 61 59 | 
             
                      # connection failures
         | 
| 62 60 | 
             
                      @@failover_mutex = Mutex.new
         | 
| 63 | 
            -
                      # Wrap internal networking calls with retry logic
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                      # Do not stub out :send_message_with_gle or :send_message
         | 
| 66 | 
            -
                      # It modifies the message, see CollectionWriter#send_write_operation
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                      def receive_message(*args)
         | 
| 69 | 
            -
                        retry_on_connection_failure do
         | 
| 70 | 
            -
                          receive_message_original *args
         | 
| 71 | 
            -
                        end
         | 
| 72 | 
            -
                      end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                      def connect(*args)
         | 
| 75 | 
            -
                        retry_on_connection_failure do
         | 
| 76 | 
            -
                          connect_original *args
         | 
| 77 | 
            -
                        end
         | 
| 78 | 
            -
                      end
         | 
| 79 61 |  | 
| 80 62 | 
             
                      protected
         | 
| 81 63 |  | 
| @@ -103,19 +85,21 @@ module MongoHA | |
| 103 85 | 
             
                  # Example:
         | 
| 104 86 | 
             
                  #   connection.retry_on_connection_failure { |retried| connection.ping }
         | 
| 105 87 | 
             
                  def retry_on_connection_failure(&block)
         | 
| 106 | 
            -
                    raise  | 
| 107 | 
            -
                     | 
| 88 | 
            +
                    raise 'Missing mandatory block parameter on call to Mongo::Connection#retry_on_connection_failure' unless block
         | 
| 89 | 
            +
                    # No need to double retry calls
         | 
| 90 | 
            +
                    return block.call(false) if Thread.current[:mongo_ha_active?]
         | 
| 91 | 
            +
                    retried        = false
         | 
| 108 92 | 
             
                    mongos_retries = 0
         | 
| 109 93 | 
             
                    begin
         | 
| 110 | 
            -
                       | 
| 111 | 
            -
                       | 
| 94 | 
            +
                      Thread.current[:mongo_ha_active?] = true
         | 
| 95 | 
            +
                      result                      = block.call(retried)
         | 
| 96 | 
            +
                      retried                     = false
         | 
| 112 97 | 
             
                      result
         | 
| 113 98 | 
             
                    rescue Mongo::ConnectionFailure => exc
         | 
| 114 99 | 
             
                      # Retry if reconnected, but only once to prevent an infinite loop
         | 
| 115 100 | 
             
                      logger.warn "Connection Failure: '#{exc.message}' [#{exc.error_code}]"
         | 
| 116 101 | 
             
                      if !retried && _reconnect
         | 
| 117 102 | 
             
                        retried = true
         | 
| 118 | 
            -
                        # TODO There has to be a way to flush the connection pool of all inactive connections
         | 
| 119 103 | 
             
                        retry
         | 
| 120 104 | 
             
                      end
         | 
| 121 105 | 
             
                      raise exc
         | 
| @@ -125,7 +109,7 @@ module MongoHA | |
| 125 109 | 
             
                      # it sometimes gets: "not master and slaveok=false"
         | 
| 126 110 | 
             
                      if exc.result
         | 
| 127 111 | 
             
                        error = exc.result['err'] || exc.result['errmsg']
         | 
| 128 | 
            -
                        close if error && error.include?( | 
| 112 | 
            +
                        close if error && error.include?('not master')
         | 
| 129 113 | 
             
                      end
         | 
| 130 114 |  | 
| 131 115 | 
             
                      # These get returned when connected to a local mongos router when it in turn
         | 
| @@ -140,13 +124,16 @@ module MongoHA | |
| 140 124 | 
             
                        retried = true
         | 
| 141 125 | 
             
                        Kernel.sleep(0.5)
         | 
| 142 126 | 
             
                        logger.warn "[#{primary.inspect}] Router Connection Failure. Retry ##{mongos_retries}. Exc: '#{exc.message}' [#{exc.error_code}]"
         | 
| 143 | 
            -
                        # TODO Is there a way to flush the connection pool of all inactive connections
         | 
| 144 127 | 
             
                        retry
         | 
| 145 128 | 
             
                      end
         | 
| 146 129 | 
             
                      raise exc
         | 
| 130 | 
            +
                    ensure
         | 
| 131 | 
            +
                      Thread.current[:mongo_ha_active?] = false
         | 
| 147 132 | 
             
                    end
         | 
| 148 133 | 
             
                  end
         | 
| 149 134 |  | 
| 135 | 
            +
                  protected
         | 
| 136 | 
            +
             | 
| 150 137 | 
             
                  # Call this method whenever a Mongo::ConnectionFailure Exception
         | 
| 151 138 | 
             
                  # has been raised to re-establish the connection
         | 
| 152 139 | 
             
                  #
         | 
| @@ -155,35 +142,35 @@ module MongoHA | |
| 155 142 | 
             
                  #
         | 
| 156 143 | 
             
                  # Returns whether the connection is connected again
         | 
| 157 144 | 
             
                  def _reconnect
         | 
| 158 | 
            -
                    logger.debug  | 
| 145 | 
            +
                    logger.debug 'Going to reconnect'
         | 
| 159 146 |  | 
| 160 147 | 
             
                    # Prevent other threads from invoking reconnect logic at the same time
         | 
| 161 148 | 
             
                    @@failover_mutex.synchronize do
         | 
| 162 149 | 
             
                      # Another thread may have already failed over the connection by the
         | 
| 163 150 | 
             
                      # time this threads gets in
         | 
| 151 | 
            +
                      begin
         | 
| 152 | 
            +
                        ping
         | 
| 153 | 
            +
                      rescue Mongo::ConnectionFailure
         | 
| 154 | 
            +
                        # Connection still not available, run code below
         | 
| 155 | 
            +
                      end
         | 
| 156 | 
            +
             | 
| 164 157 | 
             
                      if active?
         | 
| 165 158 | 
             
                        logger.info "Connected to: #{primary.inspect}"
         | 
| 166 159 | 
             
                        return true
         | 
| 167 160 | 
             
                      end
         | 
| 168 161 |  | 
| 169 | 
            -
                      # Close all sockets that are not checked out so that other threads not
         | 
| 170 | 
            -
                      # currently waiting on Mongo, don't get bad connections and have to
         | 
| 171 | 
            -
                      # retry each one in turn
         | 
| 172 | 
            -
                      @primary_pool.close if @primary_pool
         | 
| 173 | 
            -
             | 
| 174 162 | 
             
                      if reconnect_attempts > 0
         | 
| 175 163 | 
             
                        # Wait for other threads to finish working on their sockets
         | 
| 176 | 
            -
                        retries | 
| 164 | 
            +
                        retries       = 1
         | 
| 177 165 | 
             
                        retry_seconds = reconnect_retry_seconds
         | 
| 178 166 | 
             
                        begin
         | 
| 179 167 | 
             
                          logger.warn "Connection unavailable. Waiting: #{retry_seconds} seconds before retrying"
         | 
| 180 168 | 
             
                          sleep retry_seconds
         | 
| 181 | 
            -
                           | 
| 182 | 
            -
                          connect_original
         | 
| 169 | 
            +
                          ping
         | 
| 183 170 | 
             
                        rescue Mongo::ConnectionFailure => exc
         | 
| 184 171 | 
             
                          if retries < reconnect_attempts
         | 
| 185 | 
            -
                            retries | 
| 186 | 
            -
                            retry_seconds *= | 
| 172 | 
            +
                            retries       += 1
         | 
| 173 | 
            +
                            retry_seconds *= reconnect_retry_multiplier
         | 
| 187 174 | 
             
                            retry_seconds = reconnect_max_retry_seconds if retry_seconds > reconnect_max_retry_seconds
         | 
| 188 175 | 
             
                            retry
         | 
| 189 176 | 
             
                          end
         | 
| @@ -195,9 +182,8 @@ module MongoHA | |
| 195 182 | 
             
                      end
         | 
| 196 183 | 
             
                      connected?
         | 
| 197 184 | 
             
                    end
         | 
| 198 | 
            -
             | 
| 199 185 | 
             
                  end
         | 
| 200 186 |  | 
| 201 187 | 
             
                end
         | 
| 202 188 | 
             
              end
         | 
| 203 | 
            -
            end
         | 
| 189 | 
            +
            end
         | 
    
        data/lib/mongo_ha/version.rb
    CHANGED
    
    
    
        data/test/readme.md
    ADDED
    
    | @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            ## Testing
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Unfortunately the only way to properly test mongo_ha is to startup a console with connections
         | 
| 4 | 
            +
            active and to stop / restart the mongo servers in the replicaset as follows:
         | 
| 5 | 
            +
             | 
| 6 | 
            +
             | 
| 7 | 
            +
            #### Run the following code in a console
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ```ruby
         | 
| 10 | 
            +
            collection = Cache::Identity.database['test']
         | 
| 11 | 
            +
            collection.drop
         | 
| 12 | 
            +
            threads = 5.times.collect do |i|
         | 
| 13 | 
            +
              Thread.new do
         | 
| 14 | 
            +
                100.times do |j|
         | 
| 15 | 
            +
                  1_000.times do |k|
         | 
| 16 | 
            +
                    collection.insert(_id: "#{i}-#{j}-#{k}")
         | 
| 17 | 
            +
                    collection.find_one(_id: "#{i}-#{j}-#{k}")
         | 
| 18 | 
            +
                    puts("#{i}-#{j}-#{k}") if k % 1000 == 0
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  puts "#{i}-#{j} pausing"
         | 
| 21 | 
            +
                  sleep 5
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                puts "#{i} Complete"
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
            ```
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            #### Steps
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            While running the above code in the console
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            * Stop 1 slave server
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            Nothing should appear in the logs and everything should process fine
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            * Stop another slave
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            The logs should show retries
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            * Start up one of the 2 slaves that were stopped
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            The processing should resume successfully
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            #### To stop the test
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            ```ruby
         | 
| 47 | 
            +
            threads.each(&:kill)
         | 
| 48 | 
            +
            ```
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: mongo_ha
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.12. | 
| 4 | 
            +
              version: 1.12.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Reid Morrison
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2015- | 
| 11 | 
            +
            date: 2015-09-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: mongo
         | 
| @@ -16,14 +16,14 @@ dependencies: | |
| 16 16 | 
             
                requirements:
         | 
| 17 17 | 
             
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: '1. | 
| 19 | 
            +
                    version: '1.10'
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 24 | 
             
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: '1. | 
| 26 | 
            +
                    version: '1.10'
         | 
| 27 27 | 
             
            description: Automatic reconnects and recovery when replica-set changes, or connections
         | 
| 28 28 | 
             
              are lost, with transparent recovery
         | 
| 29 29 | 
             
            email:
         | 
| @@ -37,6 +37,7 @@ files: | |
| 37 37 | 
             
            - lib/mongo_ha.rb
         | 
| 38 38 | 
             
            - lib/mongo_ha/mongo_client.rb
         | 
| 39 39 | 
             
            - lib/mongo_ha/version.rb
         | 
| 40 | 
            +
            - test/readme.md
         | 
| 40 41 | 
             
            homepage: https://github.com/reidmorrison/mongo_ha
         | 
| 41 42 | 
             
            licenses:
         | 
| 42 43 | 
             
            - Apache License V2.0
         | 
| @@ -57,8 +58,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 57 58 | 
             
                  version: '0'
         | 
| 58 59 | 
             
            requirements: []
         | 
| 59 60 | 
             
            rubyforge_project: 
         | 
| 60 | 
            -
            rubygems_version: 2.4.5
         | 
| 61 | 
            +
            rubygems_version: 2.4.5.1
         | 
| 61 62 | 
             
            signing_key: 
         | 
| 62 63 | 
             
            specification_version: 4
         | 
| 63 64 | 
             
            summary: High availability for the mongo ruby driver
         | 
| 64 | 
            -
            test_files: | 
| 65 | 
            +
            test_files:
         | 
| 66 | 
            +
            - test/readme.md
         |