Rails 3 ActiveRecord .skip_callback безопасность потоков - PullRequest
6 голосов
/ 17 июля 2011

Безопасен ли этот поток кода?

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

Могу ли я безопасно использовать его, чтобы избежать повторного вызова одного и того же обратного вызова?

Вот пример

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

1 Ответ

6 голосов
/ 19 августа 2014

skip_callback и set_callback НЕ являются потокобезопасными. Я смог это подтвердить, пытаясь создать некоторые записи в sidekiq (многопоточный асинхронный процессор заданий). Как только я снова включаю обратные вызовы, возникает состояние гонки, которое приводит к вызову обратных вызовов. Если я прокомментирую код повторной активации обратного вызова, проблем не будет.

Я нашел несколько возможных решений этой проблемы, включая два драгоценных камня:

  • драгоценный камень 'sneaky-save'
  • камень 'skip_activerecord_callbacks'

Драгоценный камень подлого спасения, кажется, самый прямой и раскрывающий намерения вариант здесь. Драгоценный камень по существу обходит методы постоянства ActiveRecord и выполняет прямой sql.

Это также единственный, который я могу с уверенностью сказать, является потокобезопасным. Это также очень маленький и понятный камень. Недостатком является то, что он не вызывает проверки. Таким образом, вы должны будете сами вызывать проверки.

Ананд А. Бейт собрал большое количество вариантов. Я скептически отношусь к тому, что все пять вариантов безопасны. Два драгоценных камня, упомянутых выше, перечислены вместе с другими возможными вариантами в сообщении Ананда здесь: http://www.allerin.com/blog/save-an-object-skipping-callbacks-in-rails-3-application/

...