Skip to content

Commit

Permalink
feature(voucher):single-instance service with mutex for thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
Seelly committed Sep 6, 2024
1 parent 804f640 commit 814037f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
23 changes: 18 additions & 5 deletions biz/dal/mysql/voucher.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package mysql
import (
"context"
"errors"
"fmt"
"gorm.io/gorm"
"xzdp/biz/model/voucher"
)
Expand All @@ -25,16 +26,28 @@ func QueryVoucherByID(ctx context.Context, id int64) (*voucher.SeckillVoucher, e
return &seckillVoucher, err
}

func QueryVoucherOrderByVoucherID(ctx context.Context, userId int64, id int64) (*voucher.VoucherOrder, error) {
func QueryVoucherOrderByVoucherID(ctx context.Context, userId int64, id int64) error {
var voucherOrder voucher.VoucherOrder
if !errors.Is(DB.WithContext(ctx).Where("voucher_id = ? and user_id=?", id, userId).Limit(1).Find(&voucherOrder).Error, gorm.ErrRecordNotFound) {
return nil, errors.New("重复下单")
err = DB.WithContext(ctx).Where("voucher_id = ? and user_id=?", id, userId).Limit(1).Find(&voucherOrder).Error
fmt.Printf("voucherOrder: %v\n", voucherOrder)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("重复下单")
}
} else if voucherOrder.ID != 0 {
return errors.New("重复下单")
}
return &voucherOrder, nil
return nil
}

func UpdateVoucherStock(ctx context.Context, id int64) error {
return DB.WithContext(ctx).Model(&voucher.SeckillVoucher{}).Where("voucher_id = ?", id).Update("stock", gorm.Expr("stock - ?", 1)).Error
result := DB.WithContext(ctx).Model(&voucher.SeckillVoucher{}).
Where("voucher_id = ? and stock > 0", id).
Update("stock", gorm.Expr("stock - ?", 1))
if result.RowsAffected == 0 {
return errors.New("库存不足,扣减失败")
}
return result.Error
}

func CreateVoucherOrder(ctx context.Context, voucherOrder *voucher.VoucherOrder) error {
Expand Down
19 changes: 14 additions & 5 deletions biz/service/voucher/seckill_voucher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"github.com/cloudwego/hertz/pkg/app"
"sync"
"time"
"xzdp/biz/dal/mysql"
"xzdp/biz/dal/redis"
Expand All @@ -16,6 +17,8 @@ type SeckillVoucherService struct {
Context context.Context
}

var mu sync.Mutex

func NewSeckillVoucherService(Context context.Context, RequestContext *app.RequestContext) *SeckillVoucherService {
return &SeckillVoucherService{RequestContext: RequestContext, Context: Context}
}
Expand Down Expand Up @@ -46,14 +49,20 @@ func (h *SeckillVoucherService) Run(req *int64) (resp *int64, err error) {
if voucher.GetStock() <= 0 {
return nil, errors.New("已抢空")
}
mu.Lock()
defer mu.Unlock()
return h.createOrder(*req)
}

func (h *SeckillVoucherService) createOrder(voucherId int64) (resp *int64, err error) {
//3.判断是否已经购买
userId := utils.GetUser(h.Context).GetID()
order, err := mysql.QueryVoucherOrderByVoucherID(h.Context, userId, *req)
if order != nil {
err = mysql.QueryVoucherOrderByVoucherID(h.Context, userId, voucherId)
if err != nil {
return nil, err
}
//4.扣减库存
err = mysql.UpdateVoucherStock(h.Context, *req)
err = mysql.UpdateVoucherStock(h.Context, voucherId)
if err != nil {
return nil, err
}
Expand All @@ -64,9 +73,9 @@ func (h *SeckillVoucherService) Run(req *int64) (resp *int64, err error) {
}
voucherOrder := &voucherModel.VoucherOrder{
UserId: userId,
VoucherId: *req,
VoucherId: voucherId,
OrderId: orderId,
PayTime: time.Now().Format(layout),
PayTime: time.Now().Format("2006-01-02T15:04:05+08:00"),
UseTime: "0000-00-00 00:00:00",
RefundTime: "0000-00-00 00:00:00",
}
Expand Down

0 comments on commit 814037f

Please sign in to comment.