Ruby MongoId:回调中的竞争条件

问题描述

我有模特:

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

想象一下是否执行了以下代码,当变量ab收到相同的文档,并且函数update!用相同的参数name: 'foo'执行时。因此,在第一个更新中应该调用函数my_callback,但是在第二个更新中不应该调用函数

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

如何阻止功能my_callback在第二次更新中运行?

解决方法

脏跟踪(foo_changed?方法)完全在客户端执行。

下面将创建两个单独的模型对象:

a = MyModel.last
b = MyModel.last

更新a时,应用程序不知道ab引用数据库中的同一文档。就应用程序而言,在a.update!调用之后,b仍具有name的原始值(您可以验证)。

因此,当您发出b.update!时,存储在name中的b 的值 已更改,并且您的回调为调用。

要了解数据库中的值是否已更改,您可以使用条件更新来进行更改。[enter link description here][1]