samedi 6 octobre 2018

Ruby: Right way to do optimistic locking?

Context: Product is getting updated by multiple threads. So it leads the race condition. So I am using optimistic locking because it is frequently not updated. For latest update state of the product is determined by updated_at attribute.

For example, Prod (id=1) is updated at t1 on the machine:1. Same product(id=1) is updated at t2 on the machine:2. Now the state of Prod (id=1) on the machine:1 is stale.

Approach To determine stale: I will compare the value of updated_at on the machine with the store value of updated_atin the database value.

My main concern is setting the value of @original_updated_at. Should I use attr_writer :original_updated_at. Is this right way do optimistic locking.

attr_accessor : :original_updated_at
  def original_updated_at
    @original_updated_at || updated_at.to_f
  end


  def stale_object?
    if updated_at.to_f > original_updated_at.to_f
      @original_updated_at = nil
      return true
    else
      @original_updated_at = updated_at.to_f
      return false
    end
  end

  def recalculate
    tries = 0
    begin
      raise Product::StaleObjectError.new("StaleObjectError") if stale_object?
      attributes["updated_at"] = Time.now.utc
      Product.where(:id => self.id).update_all(attributes)
      self.attributes = attributes
    rescue Product::StaleObjectError => e
      if tries < MAX_RETRIES
        tries += 1
        sleep(1 + tries)
        reload
        retry
      else
        raise Product::StaleObjectError("StaleObjectError")
      end
    end
  end

Aucun commentaire:

Enregistrer un commentaire