Files
toutoukan/kills/kill.go

78 lines
2.3 KiB
Go
Raw Normal View History

2025-09-13 20:00:27 +08:00
package kills
import (
2025-09-14 17:01:36 +08:00
"context"
2025-09-13 20:00:27 +08:00
"encoding/base64"
"fmt"
"github.com/gin-gonic/gin"
"log"
"math/rand"
2025-09-14 21:12:37 +08:00
"net/http"
2025-09-13 20:00:27 +08:00
"time"
2025-09-14 17:01:36 +08:00
"toutoukan/init/redisInit"
2025-09-14 21:12:37 +08:00
"toutoukan/model/usermodel/userOrder"
"toutoukan/rocketmq/killmq/mqproducer"
2025-09-14 17:01:36 +08:00
"toutoukan/utill/scripts"
2025-09-13 20:00:27 +08:00
)
func GenerateOrderID() string {
2025-09-14 17:01:36 +08:00
timestamp := time.Now().Format("20060102150405")
2025-09-13 20:00:27 +08:00
2025-09-14 17:01:36 +08:00
randomBytes := make([]byte, 8)
2025-09-13 20:00:27 +08:00
_, err := rand.Read(randomBytes)
if err != nil {
return fmt.Sprintf("ORD%s%011d", timestamp, time.Now().UnixNano()%100000000000)
}
2025-09-14 17:01:36 +08:00
randomStr := base64.URLEncoding.EncodeToString(randomBytes)[:11]
2025-09-13 20:00:27 +08:00
return fmt.Sprintf("ORD%s%s", timestamp, randomStr)
}
func Userkill(c *gin.Context) {
2025-09-14 21:12:37 +08:00
var req userOrder.UserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误", "detail": err.Error()})
return
}
fmt.Printf("用户%d请求购买%s", req.UserID, req.Order)
OrderID := GenerateOrderID()
2025-09-13 20:00:27 +08:00
2025-09-14 21:12:37 +08:00
// 1. Redis扣减库存不变
result, err := redisInit.RedisClient.Eval(context.Background(), scripts.Luascript_forkill, []string{req.Order, "mayiming"}, 1, OrderID).Int()
2025-09-14 17:01:36 +08:00
if err != nil {
log.Printf("Redis 脚本执行错误: %v", err)
c.JSON(500, gin.H{"error": "库存操作失败", "detail": err.Error()})
2025-09-13 20:00:27 +08:00
return
}
2025-09-14 21:12:37 +08:00
if result != 1 {
2025-09-14 17:01:36 +08:00
c.JSON(200, gin.H{"result": "库存不足,扣减失败"})
2025-09-14 21:12:37 +08:00
return
2025-09-13 20:00:27 +08:00
}
2025-09-14 21:12:37 +08:00
// 2. 发送MQ消息关键发送失败需回滚Redis
msgSent := false
defer func() {
// 若消息未发送成功回滚Redis库存
if !msgSent {
log.Printf("消息发送失败回滚Redis库存商品: %s用户: %d", req.Order, req.UserID)
// 回滚Redis库存+1同时移除可能的订单记录根据Lua脚本逻辑调整
redisInit.RedisClient.Incr(context.Background(), req.Order)
// 若Lua脚本中记录了订单ID如存到set中也需删除
//redisInit.RedisClient.SRem(context.Background(), req.Order, OrderID)
}
}()
2025-09-14 17:01:36 +08:00
2025-09-14 21:12:37 +08:00
// 发送消息(同步发送,确保拿到发送结果)
sendErr := mqproducer.SendNormalMessage(OrderID, req.Order, req.UserID)
if sendErr != nil {
log.Printf("MQ消息发送失败: %v", sendErr)
c.JSON(500, gin.H{"error": "消息发送失败", "detail": sendErr.Error()})
return
}
// 消息发送成功标记为已发送避免defer回滚
msgSent = true
c.JSON(200, gin.H{"result": "库存扣减成功"})
}