Назад к вопросам
2gis
Senior
2
Как атомарно реализовать проверку доступности и создание заказа при выносе логики в сервис?
Компании, где спрашивали
Ответ от нейросети
sobes.tech AI
Для атомарной проверки доступности и создания заказа в сервисе на Go обычно используют транзакции базы данных. В рамках одной транзакции сначала проверяется доступность (например, наличие товара на складе), затем создаётся заказ. Если что-то идёт не так — транзакция откатывается, что гарантирует консистентность данных.
Пример с использованием базы данных и пакета database/sql:
func CreateOrderIfAvailable(db *sql.DB, productID int, quantity int, userID int) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
var available int
err = tx.QueryRow("SELECT stock FROM products WHERE id = ? FOR UPDATE", productID).Scan(&available)
if err != nil {
return err
}
if available < quantity {
return fmt.Errorf("not enough stock")
}
_, err = tx.Exec("UPDATE products SET stock = stock - ? WHERE id = ?", quantity, productID)
if err != nil {
return err
}
_, err = tx.Exec("INSERT INTO orders (user_id, product_id, quantity) VALUES (?, ?, ?)", userID, productID, quantity)
if err != nil {
return err
}
return tx.Commit()
}
Здесь FOR UPDATE блокирует строку с товаром, предотвращая гонки при параллельных запросах. Вся логика в сервисе оборачивается в транзакцию, что обеспечивает атомарность операции.