开发者

Can I use optimistic locking of an object to guard its associations?

We're running into problems with a race condition in our rails app. Here's a bit of (simplified) code before I explain:

class Message < ActiveRecord::Base
  belongs_to :question
end

class Question < ActiveRecord::Base
  has_many :messages

  def create_or_update_sending_message
    sending_message = messages.detect {|m| m.status == 'sending'}
    sending_message ||= messages.create :status => 'sending'
    sending_message
  end

  def validate
    errors.add_to_base('cannot have multiple sending messages') if messages.select {|m| m.status == 'sending'}.count > 1
  end
end

What's happening is that create_or_update_sending_message is being called from two processes. Both see the messages collection as empty, so both create a new message. Then a third process loads the question, modifies it, tries to save it, and we get an error thrown in a place that isn't where the actual problem occurred.

I can think of a few ways to avoid this if we were designing from scratch, but unfortunately create_or_update_sending_message is too deep in legacy code for this to be practical.

We have optimistic locking enabled for our Question model. It doesn't help because the question isn't being saved - only its messages are.

Is there a way to use the optimistic locking on the question to guard against the saving of the creation of the message? So it would look something like

def create_or_update_sending_message
  self.optimistically_lock do |lock|
    sending_message = messages.detect {|m| m.status == 'sending'}
    sending_message ||= 开发者_StackOverflowmessages.create_with_optimistic_lock lock, :status => 'sending'
    sending_message
  end
end

Does that even make sense from a database point of view?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜