-
Type: Bug
-
Resolution: Fixed
-
Priority: Critical - P2
-
Affects Version/s: 9.0.1
-
Component/s: Persistence
-
None
-
Ruby Drivers
-
Not Needed
-
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.