The model deletion in Ruby on Rails (Rspec) is not deleting the item ontime, just later (Database: Mongo with Replica Sets)

62 Views Asked by At

First, I'm using Mongo with the read preference of the replica sets configured as secondary, which can cause the asynchronous replication behavior

I have the following code in my automated tests:

1.  context 'success' doz
2.    before do
3.      @role = Role.create!(name: 'admin')
4.
5.      @count_before = Role.count
6.      @role.destroy!
7.      @count_after1 = Role.count # => 1
8.      @count_after2 = Role.count # => 0
9.      @count_after3 = Role.count # => 0
10.     @count_after4 = Role.count # => 0
11.     @count_after5 = Role.count # => 0
12.     @count_after6 = Role.count # => 0
13.   end
14
15.   it 'should delete properly' do
16.     expect(@count_after1).to be_eql(@count_before - 1)
17.   end
18. end

However, somehow

  1. the @cound_after1 (line 7) has the 1 value (the outdated one, because the Role item was deleted in line 6;
  2. the @count_after2 (line 8) has the 0 value (the correct one).

More than that, this behavior happens intermittently. Sometimes it works and all @count_afters has the 0 value, sometimes it doesn't and @count_after1 is have the 1 value.

Changing the read_preference of the mongoid.yml file from secondary to primary is not a valid solution, because we need to reproduce the production environment on the test suite properly.

How can we fix that?

I tried to debug the code and sadly I still didn't discover a possible solution to this issue. It looks like this is due to an asynchronous issue, because the Role item is deleted afterwards. It is also good to note that this issue happens intermittently: Sometimes the test pass and sometimes it doesn't.

1

There are 1 best solutions below

3
Joe On

That behavior is not a bug.

From the docs you linked:

All read preference modes except primary may return stale data because secondaries replicate operations from the primary in an asynchronous process. Ensure that your application can tolerate stale data if you choose to use a non-primary mode.

All data is written to the primary. It then takes non-zero time to replicate that data to the secondary nodes.

If you need to ensure all nodes in the replica set have processed the write, you could use the write concern "w:all" instead of the default "w:1".