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
想象一下,如果执行以下代码,当变量a
和b
接收相同的文档并且函数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
时,应用程序不知道a
和b
引用数据库中的同一个文档。就应用而言,在a.update!
调用之后,b
仍然具有name
的原始值(您可以验证)。
因此,当您发出b.update!
时,name
的值存储在b
已 更改并且您的回调被调用。
要查明数据库中的值是否发生变化,您可以使用条件更新等方法。[enter link description here][1]
【讨论】:
以上是关于Ruby MongoId:回调中的竞争条件的主要内容,如果未能解决你的问题,请参考以下文章
批量查找 mongoDB 记录(使用 mongoid ruby 适配器)