Ruby MongoId:回调中的竞争条件

Posted

技术标签:

【中文标题】Ruby MongoId:回调中的竞争条件【英文标题】:Ruby MongoId: race condition in callbacks 【发布时间】:2020-10-23 23:37:26 【问题描述】:

我有模特:

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在第二次更新中运行?

【问题讨论】:

我建议阅读 Rails 指南中的 locking records for update。 【参考方案1】:

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

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

a = MyModel.last
b = MyModel.last

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

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

要查明数据库中的值是否发生变化,您可以使用条件更新等方法。[enter link description here][1]

【讨论】:

以上是关于Ruby MongoId:回调中的竞争条件的主要内容,如果未能解决你的问题,请参考以下文章

批量查找 mongoDB 记录(使用 mongoid ruby​​ 适配器)

如何跳过 Mongoid 文档的回调?

如何使用 ruby​​ 编程设置 mongoid

Mongoid 在 ruby​​ 1.9.3 上失败

使用 Mongoid 和 Ruby 查询最近 30 天的日期范围?

CreateTimerQueueTimer 回调和竞争条件