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
- the
@cound_after1(line 7) has the1value (the outdated one, because the Role item was deleted in line 6; - the
@count_after2(line 8) has the0value (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.
That behavior is not a bug.
From the docs you linked:
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".