在更新数据库提交后运行rails代码,没有after_commit

Bri*_*ian 10 postgresql ruby-on-rails resque ruby-on-rails-3

我正在尝试与我的后台任务经理对抗一些种族案件.基本上,我有一个Thing对象(已经存在)并为其分配一些属性,然后保存它.使用新属性保存后,我将其排入Resque,并传入ID.

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

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

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

我们知道这是一个竞争案例,因为rails将thing.save 在数据实际提交到数据库之前返回(在本例中为postgresql).

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

Edi*_*ges 4

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

transaction do
  thing = Thing.find(1)
  puts thing.foo # outputs "old value"
  thing.foo = "new value"
  thing.save
end
ThingProcessor.queue_job(thing.id)
Run Code Online (Sandbox Code Playgroud)

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