提交对数据库的更新后运行rails代码,而无需after_commit [英] Run rails code after an update to the database has commited, without after_commit

查看:87
本文介绍了提交对数据库的更新后运行rails代码,而无需after_commit的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图与我的后台任务管理器抗衡一些种族问题。本质上,我有一个 Thing 对象(已经存在),并为其分配了一些属性,然后保存它。将其保存为新属性后,我将其在Resque中排队,并传递ID。

I'm trying to battle some race cases with my background task manager. Essentially, I have a Thing object (already exists) and assign it some properties, and then save it. After it is saved with the new properties, I queue it in Resque, passing in the 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)<从数据库中加载对象/ code>。

The background job will load the object from the database using Thing.find(thing_id).

问题是我们发现Resque能够如此迅速地接载工作并加载 Thing 对象从ID,它加载一个陈旧的对象。因此,在工作中,调用 thing.foo 仍会返回旧值,例如1/100倍(不是真实数据,但不会经常发生)。

The problem is that we've found Resque is so fast at picking up the job and loading the Thing object from the ID, that it loads a stale object. So within the job, calling thing.foo will still return "old value" like 1/100 times (not real data, but it does not happen often).

我们知道这是一个竞赛案例,因为在实际获得数据之前,rails将从 thing.save 返回

We know this is a race case, because rails will return from thing.save before the data has actually been commit to the database (postgresql in this case).

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

Is there a way in Rails to only execute code AFTER a database action has commit? Essentially I want to make sure that by the time Resque loads the object, it is getting the freshest object. I know this can be achieved using an after_commit hook on the Thing model, but I don't want it there. I only need this to happen in this one specific context, not every time the model has commit changed to the DB.

推荐答案

您也可以进行交易。就像下面的示例一样:

You can put in a transaction as well. Just like the example below:

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






更新:有一个宝石可以调用交易后,您可以用它解决你的问题。这是链接:
http://xtargets.com/2012/03/08/understanding-and-solving-race-conditions-with-ruby-rails-and-background-workers/

这篇关于提交对数据库的更新后运行rails代码,而无需after_commit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆