在对数据库进行更新后,运行rails代码,不需要after_commit。[英] Run rails code after an update to the database has commited, without after_commit

本文是小编为大家收集整理的关于在对数据库进行更新后,运行rails代码,不需要after_commit。的处理方法,想解了在对数据库进行更新后,运行rails代码,不需要after_commit。的问题怎么解决?在对数据库进行更新后,运行rails代码,不需要after_commit。问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我正在尝试与我的后台任务管理器对抗一些比赛案例.本质上,我有一个 Thing 对象(已经存在)并为其分配了一些属性,然后保存它.在它与新属性一起保存后,我在 Resque 中对其进行排队,并传入 ID.

thing = Thing.find(1)
puts thing.foo # outputs "old value"
thing.foo = "new value"
thing.save
ThingProcessor.queue_job(thing.id)

后台作业将使用 Thing.find(thing_id) 从数据库加载对象.

问题在于,我们发现 Resque 在获取作业并从 ID 加载 Thing 对象方面非常快,以至于它加载了一个陈旧的对象.因此,在作业中,调用 thing.foo 仍会返回 1/100 倍的"旧值"(不是真实数据,但并不经常发生).

我们知道这是一个竞争案例,因为 rails 会在数据实际提交到数据库之前从 thing.save 返回(在这种情况下是 postgresql).

Rails 中是否有办法只在数据库操作提交后执行代码?本质上,我想确保在 Resque 加载对象时,它正在获取最新的对象.我知道这可以使用 Thing 模型上的 after_commit 钩子来实现,但我不希望它在那里.我只需要在这个特定的上下文中发生这种情况,而不是每次模型提交更改到数据库时.

推荐答案

您也可以进行交易.就像下面的例子:

transaction do
  thing = Thing.find(1)
  puts thing.foo # outputs "old value"
  thing.foo = "new value"
  thing.save
end
ThingProcessor.queue_job(thing.id)
<小时>

更新:有一个调用 After Transaction 的 gem,这样你可以解决你的问题.链接在这里:http://xtargets.com/2012/03/08/understanding-and-solving-race-conditions-with-ruby-rails-and-background-workers/

本文地址:https://www.itbaoku.cn/post/1763745.html