ruby-on-railspostgresqlactiverecordlockingpessimistic-locking

does with_lock lock everything inside the block?


Does with_lock lock all models in the block or just the model itself? For example in the following are all the item models inside with_lock locked or is just the entry model locked?

class Entry < ApplicationRecord
  enum state: [:pending, :posted]
    
  has_many :items, dependent: :destroy
 
  def post!
    with_lock do
      return unless pending?
      items.each { |i| i.post! }
      self.posted!
    end
  end
end

Solution

  • with_lock gets a row-level pessimistic lock on a single instance. with_lock simply combines the lock and transaction statements into one, so it is equivalent to:

    Entity.transaction do
      entity_instance.lock!
    end
    

    You are calling with_lock inside a model, so you are actually doing self.with_lock. That is, you are obtaining a lock on the current instance of Entity. The individual Item records do not get locked unless you explicitly lock them as well. Changes to them do get included in the same parent transaction, though.