Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-5815

Regression in the client_override behavior with find_or_create_by (and likely other methods)

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Critical - P2 Critical - P2
    • 9.0.3
    • Affects Version/s: 9.0.1
    • Component/s: Persistence
    • None
    • Ruby Drivers
    • Not Needed
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      Just noticed what appears to be an important regression in Mongoid 9.0.1.

      When using client_override with find_or_create_by method (and maybe others), Mongoid is using the right client (override) for the find and then the wrong client for the insert !!

      This can leads not only to duplication but also to writes in the totally wrong database.
      Here is a reproduction script I wrote:

      #!/usr/bin/env ruby
      
      require 'bundler/inline'
      
      gemfile do
        source 'https://rubygems.org'
        gem 'mongoid', '~> 8.0'
      end
      
      puts "Mongoid #{Mongoid::VERSION}\n============="
      
      Mongoid.configure do |config|
        config.load_configuration(
          clients: {
            default: {
              hosts: ['localhost:27017'],
              database: 'default_db',
            },
            shard1: {
              hosts: ['localhost:27017'],
              database: 'shard_db',
            }
          }
        )
        config.log_level = :debug
      end
      Mongoid.purge!
      
      class Model
        include Mongoid::Document
      
        field :version, type: Integer
      end
      
      Mongoid.override_client(:shard1)
      
      # uncomment to see the log with the wrong database
      # Mongo::Logger.logger = Logger.new(STDOUT)
      
      puts "shard_db: find_or_create_by(version: 2)"
      Model.find_or_create_by(version: 2)
      puts "shard_db: find_or_create_by(version: 2)"
      Model.find_or_create_by(version: 2)
      # => the find is executed on the shard client but the insert on the default client !!!
      
      puts "in shard_db: #{Model.where(version: 2).count}"
      Mongoid.override_client(nil)
      puts "in default_db: #{Model.where(version: 2).count}"
      

      And here is the output with Mongoid 9 and 8:

      $ ruby mongoid9-client-override-bug.rb
      Mongoid 9.0.1
      =============
      shard_db: find_or_create_by(version: 2)
      shard_db: find_or_create_by(version: 2)
      in shard_db: 0
      in default_db: 2
      
      $ ruby mongoid9-client-override-bug.rb
      Mongoid 8.1.5
      =============
      shard_db: find_or_create_by(version: 2)
      shard_db: find_or_create_by(version: 2)
      in shard_db: 1
      in default_db: 0
      

      Here we can see the records being duplicated and inserted in the wrong collection.
      By uncommenting the Logger line, you can easily see the details (stripped for readability):

      shard_db.find | STARTED | {"find"=>"models", "filter"=>{"version"=>2}, "limit"=>1, "sort"=>{"_id"=>1}, "$db"=>"shard_db", "lsid"=>{"id"=><BSON::Binary:0x2260 type=uuid data=0xddc7aa020e954e92...>}}
      default_db.insert | STARTED | {"insert"=>"models", "ordered"=>true, "documents"=>[{"_id"=>BSON::ObjectId('66e2c3c4219a8e2a464a5273'), "version"=>2}], "$db"=>"default_db", "lsid"=>{"id"=><BSON::Binary:0x2300 type=uuid data=0x513f46c16c14442a...>}}
      

      I noticed this when the specs for https://github.com/adacosta/mongoid_rails_migrations (which I am helping maintain) were not passing with Mongoid 9. I hope people using multiple clients in production will have enough test to notice this before attemping the upgrading to Mongoid 9.

            Assignee:
            dmitry.rybakov@mongodb.com Dmitry Rybakov
            Reporter:
            bigbourin@gmail.com Adrien Jarthon
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: