When inserting several records simultaneously the following error is sometimes raised:
NoMethodError: undefined method `rank' for nil:NilClass
/app/vendor/bundle/ruby/3.0.0/gems/ranked-model-0.4.7/lib/ranked-model/ranker.rb line 194 in rearrange_ranks
/app/vendor/bundle/ruby/3.0.0/gems/ranked-model-0.4.7/lib/ranked-model/ranker.rb line 185 in assure_unique_position
/app/vendor/bundle/ruby/3.0.0/gems/ranked-model-0.4.7/lib/ranked-model/ranker.rb line 61 in handle_ranking
/app/vendor/bundle/ruby/3.0.0/gems/ranked-model-0.4.7/lib/ranked-model.rb line 33 in block in handle_ranking
/app/vendor/bundle/ruby/3.0.0/gems/ranked-model-0.4.7/lib/ranked-model.rb line 32 in each
/app/vendor/bundle/ruby/3.0.0/gems/ranked-model-0.4.7/lib/ranked-model.rb line 32 in handle_ranking
I was able to somewhat reliably reproduce this error with the following test:
begin
require "bundler/inline"
rescue LoadError => e
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
raise e
end
gemfile(true) do
source "https://rubygems.org"
gem "activerecord", "~> 6.1"
gem "ranked-model"
gem "pg"
end
require "active_record"
require "minitest/autorun"
require "logger"
ActiveRecord::Base.establish_connection(adapter: "postgresql", database: "ranked_model_issue", url: "postgres://postgres:@localhost:5434")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :ducks, force: true do |t|
t.string :name
t.integer :row_order
t.timestamps
end
end
class Duck < ActiveRecord::Base
include RankedModel
ranks :row_order
end
class BugTest < Minitest::Test
def test_error_during_rebalance
threads = 5.times.map do
Thread.new do
ActiveRecord::Base.connection_pool.with_connection do
Duck.create!
end
end
end
threads.each(&:join)
assert_equal Duck.count, 5
# Secondary issue
# assert_equal Duck.distinct.pluck(:row_order).size, 5
end
end
- This does not work with sqlite, as sqlite raises an error due to the database being locked.
- The test does not always fail, as is the nature with race conditions. It might take a few tries.
- This test also exhibits a secondary issue, namely that the same row_order-value is taken several times, even if it does not outright fail.
When inserting several records simultaneously the following error is sometimes raised:
I was able to somewhat reliably reproduce this error with the following test: