'Rspec Capybara Failure/Error: DatabaseCleaner.clean

I am using rails 6.1.4 (Ubuntu 20.04) and am running tests with rspec, factorybot, and capybara. I also got database_cleaner where I'm using :truncation to start each test block with a clean slate (yes, not the fastest way but the most rigorous way). When I run rspec spec (applies to individual models too), I got one table where I randomly get a bunch of failing tests saying

Failure/Error: DatabaseCleaner.clean
     
     ActiveRecord::Deadlocked:
       PG::TRDeadlockDetected: ERROR:  deadlock detected
       DETAIL:  Process 105987 waits for AccessExclusiveLock on relation 1876018 of database 1876015; blocked by process 105996.
       Process 105996 waits for AccessShareLock on relation 1876043 of database 1876015; blocked by process 105987.
       HINT:  See server log for query details.
     # ./spec/support/database_cleaner.rb:32:in `block (2 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # PG::TRDeadlockDetected:
     #   ERROR:  deadlock detected
     #   DETAIL:  Process 105987 waits for AccessExclusiveLock on relation 1876018 of database 1876015; blocked by process 105996.
     #   Process 105996 waits for AccessShareLock on relation 1876043 of database 1876015; blocked by process 105987.
     #   HINT:  See server log for query details.
     #   ./spec/support/database_cleaner.rb:32:in `block (2 levels) in <top (required)>'

It is truly random where the tests start failing, i.e. I can run the same test commands consecutively and different tests will pass / fail.

in ./spec/support/database_cleaner.rb [I cut out the comments]

    RSpec.configure do |config|
      config.before(:suite) { DatabaseCleaner.clean_with(:truncation) }
    
      config.before(:each) { DatabaseCleaner.strategy = :truncation }
    
      config.before(:each, js: true) { DatabaseCleaner.strategy = :truncation }
    
      config.before(:each) { DatabaseCleaner.start }
      config.after(:each) do
[this is row 32:]        DatabaseCleaner.clean
        rescue NoMethodError => e # See: https://github.com/DatabaseCleaner/database_cleaner-sequel/issues/4
        next puts("Warning: catch #{e.message}") if e.message == %(undefined method `rollback' for nil:NilClass (DB Cleaner gem))
          raise e
      end
    end

Sometimes, after a while, all tests may work also. Does anyone have a sense for what's causing this issue? Thank you!



Solution 1:[1]

Give some time to the database cleaner to do its job ! A dummy way of solving the issue is by using the sleep method like so: sleep(1), at the begining of each "it" block. That should do the job ?

What's hapenning is that database cleaner doesn't have the time to clean your PSQL DB that you are already trying to recreate the same instance you used in the previous test.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 flyingfishcattle