class Inventory::Reserve
class NotEnoughStock < StandardError; end
def initialize(sku:, quantity:)
@sku = sku
@quantity = Integer(quantity)
end
def call
ApplicationRecord.transaction do
item = InventoryItem.lock.find_by!(sku: @sku)
raise NotEnoughStock if item.available < @quantity
item.update!(available: item.available - @quantity)
InventoryReservation.create!(sku: @sku, quantity: @quantity)
end
end
end
Inventory systems are concurrency systems. Lock the row, verify available quantity, then write the reservation in the same transaction. It’s the simplest correct starting point.