Ruby MongoId: race condition in callbacks

162 views Asked by At

I have the Model:

class MyModel
    include Mongoid::Document

    after_save :my_callback, if: -> { name_changed? }

    field :name, type: String

    def my_callback
       # this will execute two times
       puts 'executes my callback'
       puts changes
    end
end

Imagine if the follow code is executed, when variable a and b receive the same document and the function update! is executed with the same argument name: 'foo'. So, in the first update the function my_callback should be called, but in the second update not should.

MyModel.create(name: 'bar')
a = MyModel.last
b = MyModel.last

a.update!(name: 'foo')
executes my callback
{"name"=>['bar', 'foo']}
=> true

b.update!(name: 'foo')
executes my callback -> this not can execute
{"name"=>['bar', 'foo']}
=> true

how prevent the function my_callback run in the second update?

1

There are 1 answers

0
D. SM On

Dirty tracking (foo_changed? methods) is performed entirely on the client side.

The following creates two separate model objects:

a = MyModel.last
b = MyModel.last

When you update a, the application has no idea that a and b refer to the same document in the database. As far as the application is concerned, after the a.update! call, b still has the original value for name (which you can verify).

Therefore, when you issue b.update!, the value of name as stored in b has changed and your callback is invoked.

To find out whether the value changed in the database you could use for example conditional updates.[enter link description here][1]