ActiveRecord: simultaneous access between validation and writing to the database

Let's say I have an online bookstore whose data model looks like this:

enter image description here

Before creating a new order, I want to make sure that there are enough items in stock, so I have this method

def ensure_enough_in_stock errors.add(:quantity, "not enough in stock") if quantity > book.stock end 

To make sure this method is called before saving to the database, I use validate:

 validate :ensure_enough_in_stock, :on => create 

So, to summarize when I create an order:

  • verification method called
  • the new order is written to the database (if the check passed)

What happens if between 1. and 2. another process (concurrent access, another thread, ...) modifies the stock attribute of the same book? Is an exception thrown?

More generally, how to handle cases when something happens between validation and storage in the database?

I think I should put validation in the database, but I don't know what impact this would have on performance. Is there any reasonable way to handle this situation?

EDIT

Transaction locking, as described here, prevents write access to the stock, but what happens if I also have a “published” attribute in the model book that can take the value “public” or “private”, and then I want to make sure that you You cannot buy a book that is private.

But just as the stock value can be changed by an external process, the published value can also be changed: in this case, blocking will not be of any help, is it?

enter image description here

+4
source share
1 answer

Rails typically includes validation and persistence in a transaction. Therefore, you only need to run the request with the lock in ensure_enough_in_stock . Locking will prevent other requests from modifying data. See this for a lock request.

+2
source

Source: https://habr.com/ru/post/1444567/


All Articles