Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-490

No connection refresh after ConnectionFailure exception on write

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 1.8.2
    • Affects Version/s: 1.7.0
    • Component/s: None
    • Environment:
      MongoDB 2.0.6
      mongo gem 1.7.0

      After a ConnectionFailure exception, the ruby driver tries to reconnect automatically on a "read" operation, but not on a "write" operation.

      Let's consider a basic example similar to the one given in the tutorial:

      require 'rubygems'
      require 'mongo'
      
      @conn= Mongo::Connection.new
      @db  = @conn['sample-db']
      @coll= @db['test']
      
      @coll.insert({'a' => 1})
      # => BSON::ObjectId('508696b9457d514235000001')
      
      @coll.find.each { |doc| puts doc.inspect }
      # => #<BSON::OrderedHash: ...
      
      # kill the mongod process here
      
      @coll.find.each { |doc| puts doc.inspect }
      # => Mongo::ConnectionFailure: Failed to connect to host localhost and port 27017
      
      # re-lauch the mongod process here
      
      @coll.find.each { |doc| puts doc.inspect }
      # => #<BSON::OrderedHash: ...
      

      As long as the mongod process is down, we will get a ConnectionFailure exception, but after re-lauching of the mongod process, read operations will work again.

      This is because the Cursor attempts to refresh the connection here: https://github.com/mongodb/mongo-ruby-driver/blob/1.7.0/lib/mongo/cursor.rb#L127

      But if we do the same test with a "write" operation, it will not reconnect automatically:

      require 'rubygems'
      require 'mongo'
      
      @conn= Mongo::Connection.new
      @db  = @conn['sample-db']
      @coll= @db['test']
      
      @coll.insert({'a' => 1})
      # => BSON::ObjectId('508696b9457d514235000001')
      
      # kill the mongod process here
      
      @coll.insert({'a' => 1})
      # => Mongo::ConnectionFailure: Operation failed with the following exception: Broken pipe:Broken pipe
      
      # re-lauch the mongod process here
      
      @coll.insert({'a' => 1})
      # => Mongo::ConnectionFailure: Operation failed with the following exception: Broken pipe:Broken pipe
      

      Even after the mongod process relaunch, we only get ConnectionFailure exceptions.

      With the mongo gem version 1.6.2, it used to reconnect on reads AND writes because the "send_message_on_socket" function closed the connection, see:
      https://github.com/mongodb/mongo-ruby-driver/blob/1.6.2/lib/mongo/networking.rb#L314
      It's not the case anymore, see:
      https://github.com/mongodb/mongo-ruby-driver/blob/1.7.0/lib/mongo/networking.rb#L284

      Does it work that way by design or is it a bug?

      To me, it seems to be a regression (since it worked with version 1.6.2) and it breaks code relying on the mongo gem (e.g. the central logger gem which can be stuck without being able to reconnect, although correctly implementing the retry code described in the driver's documentation).

            Assignee:
            brandon.black@10gen.com Brandon Black
            Reporter:
            maxime Maxime RETY
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: