User can purchase products with my project. However, product stock count must be equal or greater then requested quantity in purchase request. If It is ok, then a purchase record is saved on the table. After then, stock count is updated for this product in the another table. So there are 3 operations and if I send 20 concurrently requests to purchase 20 of product A which has 100 stock count in the db from another golang app, it works wrongly. It opens 20 purchase records in db and stock count updated as 60. Normally, after 5 requests operated, it must throws error because of stock count of product. I could not tweak method for this purpose. How Can I do?
This is the method, It calls repository methods 3 times but there is no special operations there only gorm save and update operations:
var wg sync.WaitGroup
wg.Add(1)
errs := make(chan error, 1)
go func(ctx context.Context, request *dto.CreateTicketPurchaseRequest) {
defer wg.Done()
productStockCount, err := t.stockRepo.GetTicketStockCount(productId) // first check available stock count
if err != nil {
errs <- err
return
}
if productStockCount.StockCount < payload.Quantity {
err = fmt.Errorf("no enough products")
errs <- err
return
}
u := new(entity.TicketPurchases)
u.Quantity = payload.Quantity
u.UserId = payload.UserId
u.StockId = productId
err = t.purchaseRepo.PurchaseTicket(u) // if stock count is ok, then purchase product
if err != nil {
errs <- err
return
}
productStockCount.StockCount = productStockCount.StockCount - u.Quantity
err = t.stockRepo.RemoveStockCount(productStockCount) // update stock count for product
if err != nil {
errs <- err
return
}
close(errs)
}(ctx, payload)
wg.Wait()
if err = <-errs; err != nil {
return c.JSON(http.StatusBadRequest, nil)
}