1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| func (s *Service) Sell(ctx context.Context, request *inventorypb.SellInfoRequest) (*emptypb.Empty, error) { tx := s.DB.Begin() for _, goodsInfo := range request.GoodsInfo {
mutex := s.RedSync.NewMutex(fmt.Sprintf("inv_%d", goodsInfo.GoodsId)) if err := mutex.Lock(); err != nil { s.Logger.Error("can not get redis lock", zap.Error(err)) return nil, status.Error(codes.Internal, "can not get redis lock") }
var inv model.Inventory res := s.DB.Where(&model.Inventory{GoodsID: goodsInfo.GoodsId}).First(&inv) if res.Error != nil { s.Logger.Error("can not get inv", zap.Error(res.Error)) return nil, status.Error(codes.Internal, "") } if res.RowsAffected == 0 { tx.Rollback() return nil, status.Error(codes.NotFound, "") } if inv.Stocks < goodsInfo.Num { tx.Rollback() return nil, status.Error(codes.ResourceExhausted, "") } inv.Stocks -= goodsInfo.Num tx.Save(&inv)
if ok, err := mutex.Unlock(); !ok || err != nil { s.Logger.Error("can not unlock redis") return nil, status.Error(codes.Internal, "") } } tx.Commit()
return &emptypb.Empty{}, nil }
|