本文介绍了Rails 3 ActiveRecord .skip_callback线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码线程安全吗?

MyModel.skip_callback(:save, :before, :my_callback)
my_model_instance.update_attributes(attributes)
MyModel.set_callback(:save, :before, :my_callback)

我可以安全地使用它来避免递归触发该回调吗?

Can i safely use it to avoid retrigger the same callback recursively?

这里是一个示例

class Blog < ActiveRecord::Base

  after_save  :update_blog_theme, :if => :active_theme_id_changed?

  # ...

  private

  def update_blog_theme

    # Reuses a previously used BlogTheme or creates a new one
    blog_theme = BlogTheme.find_by_theme_id_and_blog_id(
                      self.active_theme_id,
                      self.id)

    blog_theme ||= BlogTheme.create!(
                     :theme_id => active_theme_id,
                     :blog_id => self.id )

    Blog.skip_callback(:save, :after, :update_blog_theme)
    self.update_attributes!(:active_blog_theme_id => blog_theme.id)
    Blog.set_callback(:save, :after, :update_blog_theme)

  end

end


推荐答案

skip_callback set_callback 不是线程安全的。尝试在sidekiq(线程异步作业处理器)中创建一些记录时,我能够确认这一点。一旦我重新启用回调,就会出现争用情况,导致调用回调。如果我评论了回调重新激活代码,就没有问题。

skip_callback and set_callback are NOT thread safe. I was able to confirm this while trying to create some records within sidekiq (a threaded async job processor). As soon as I re-enable the callbacks, there is a race condition that results in callbacks being called. If I comment the callback re-activation code, there are no issues.

我发现了许多可能的解决方案,其中包括两个宝石:

I have found a number of possible solutions to the issue including two gems:


  • 偷偷摸摸地保存的宝石

  • skip_activerecord_callbacks宝石

偷偷摸摸地保存着的宝石似乎是这里最直接,最意图揭示的选择。 gem本质上绕过ActiveRecord持久性方法并执行直接的sql。

The sneaky-save gem seems to be the most straight-forward and intention-revealing option here. The gem essentially bypasses the ActiveRecord persistence methods and executes straight sql.

这也是我唯一可以确信地说是线程安全的。这也是一个很小且可以理解的宝石。缺点是它不调用验证。因此,您将需要自己调用验证。

It is also the only one that I can confidently say is thread-safe. It is also a very small and understandable gem. The downside is that it does not call validations. Thus you would need to call validations yourself.

Anand A. Bait在许多选项上花了很多功夫。我怀疑所有五个选项都是线程安全的。上面提到的两个宝石在Anand的文章中列出了其他可能选项:

Anand A. Bait put together a great rundown on a number options. I am skeptical that all five options are threadsafe. The two gems mentioned above are listed along with other possible options in Anand's post here: http://www.allerin.com/blog/save-an-object-skipping-callbacks-in-rails-3-application/

这篇关于Rails 3 ActiveRecord .skip_callback线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 19:20