新需求-活动需求-盲盒转盘调通盘-调试-优化错误
This commit is contained in:
@@ -36,6 +36,9 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
*/
|
*/
|
||||||
public function draw_gift($gift_bag_id, $user_id, $gift_user_ids, $num = 1, $room_id = 0, $heart_id = 0,$auction_id = 0)
|
public function draw_gift($gift_bag_id, $user_id, $gift_user_ids, $num = 1, $room_id = 0, $heart_id = 0,$auction_id = 0)
|
||||||
{
|
{
|
||||||
|
// 最大重试次数
|
||||||
|
$maxRetries = 3;
|
||||||
|
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
|
||||||
try {
|
try {
|
||||||
// 1. 验证参数并提前处理错误
|
// 1. 验证参数并提前处理错误
|
||||||
$validationResult = $this->validateDrawParameters($gift_bag_id, $user_id, $gift_user_ids);
|
$validationResult = $this->validateDrawParameters($gift_bag_id, $user_id, $gift_user_ids);
|
||||||
@@ -111,10 +114,18 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
'heart_id' => $heart_id,
|
'heart_id' => $heart_id,
|
||||||
'auction_id' => $auction_id,
|
'auction_id' => $auction_id,
|
||||||
];
|
];
|
||||||
|
if ($this->redis) {
|
||||||
$this->redis->setex($key, 86400 * 7, $e->getMessage() . ' ' . json_encode($errorData));
|
$this->redis->setex($key, 86400 * 7, $e->getMessage() . ' ' . json_encode($errorData));
|
||||||
|
}
|
||||||
|
// 如果是死锁且还有重试机会
|
||||||
|
if (strpos($e->getMessage(), 'Deadlock') !== false && $attempt < $maxRetries - 1) {
|
||||||
|
// 随机延迟后重试
|
||||||
|
usleep(rand(50000, 200000)); // 50-200ms
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return ['code' => 0, 'msg' => "网络加载失败,请重试!", 'data' => null];
|
return ['code' => 0, 'msg' => "网络加载失败,请重试!", 'data' => null];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 验证抽奖参数
|
* 验证抽奖参数
|
||||||
@@ -471,9 +482,16 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
$gift_user_num = count(explode(',', $gift_user_ids)); //人数
|
$gift_user_num = count(explode(',', $gift_user_ids)); //人数
|
||||||
$bagGiftPrice = $bag_data['gift_price'] * $num * $gift_user_num;
|
$bagGiftPrice = $bag_data['gift_price'] * $num * $gift_user_num;
|
||||||
|
|
||||||
db::startTrans();
|
// 增加重试机制
|
||||||
|
$maxRetries = 3;
|
||||||
|
for ($retry = 0; $retry < $maxRetries; $retry++) {
|
||||||
try {
|
try {
|
||||||
// 1. 创建抽奖记录
|
db::startTrans();
|
||||||
|
// 按照固定顺序处理事务步骤
|
||||||
|
// 1. 扣除用户金币(优先处理)
|
||||||
|
$this->deductUserCoins($user_id, $bagGiftPrice, $room_id);
|
||||||
|
|
||||||
|
// 2. 创建抽奖记录
|
||||||
$boxTurntableLog = db::name('vs_blind_box_turntable_log')->insertGetId([
|
$boxTurntableLog = db::name('vs_blind_box_turntable_log')->insertGetId([
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'gift_bag_id' => $bag_data['id'],
|
'gift_bag_id' => $bag_data['id'],
|
||||||
@@ -487,16 +505,13 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
throw new \Exception('添加盲盒转盘记录失败');
|
throw new \Exception('添加盲盒转盘记录失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 批量更新库存
|
// 3. 批量更新库存(按ID排序避免死锁)
|
||||||
$this->batchUpdateGiftInventory($availableGiftss, $room_id);
|
$this->batchUpdateGiftInventory($availableGiftss, $room_id);
|
||||||
|
|
||||||
// 3. 批量插入礼包发放记录
|
// 4. 批量插入礼包发放记录
|
||||||
$this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults);
|
$this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults);
|
||||||
|
|
||||||
// 4. 扣除用户金币
|
// 5. 发送礼物
|
||||||
$this->deductUserCoins($user_id, $bagGiftPrice, $room_id);
|
|
||||||
|
|
||||||
//发送礼物
|
|
||||||
$result = $this->sendGiftsToRecipients($precomputedResults, $room_id,$user_id,$heart_id,$auction_id);
|
$result = $this->sendGiftsToRecipients($precomputedResults, $room_id,$user_id,$heart_id,$auction_id);
|
||||||
if (isset($result['code']) && $result['code'] !== 1) {
|
if (isset($result['code']) && $result['code'] !== 1) {
|
||||||
throw new \Exception($result['msg']);
|
throw new \Exception($result['msg']);
|
||||||
@@ -504,7 +519,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
|
|
||||||
db::commit();
|
db::commit();
|
||||||
|
|
||||||
// 5. 统计礼物数量
|
// 统计礼物数量
|
||||||
$giftCounts = $this->countGifts($precomputedResults);
|
$giftCounts = $this->countGifts($precomputedResults);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -517,9 +532,17 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
];
|
];
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
db::rollback();
|
db::rollback();
|
||||||
|
// 检查是否是死锁错误
|
||||||
|
if (strpos($e->getMessage(), 'Deadlock') !== false && $retry < $maxRetries - 1) {
|
||||||
|
// 等待随机时间后重试
|
||||||
|
usleep(rand(10000, 100000)); // 10-100ms
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
|
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ['code' => 0, 'msg' => '操作超时,请重试', 'data' => null];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量更新礼物库存
|
* 批量更新礼物库存
|
||||||
@@ -533,9 +556,14 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
$inventoryUpdates[$giftId] = ($inventoryUpdates[$giftId] ?? 0) + 1;
|
$inventoryUpdates[$giftId] = ($inventoryUpdates[$giftId] ?? 0) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按ID排序避免死锁
|
||||||
|
ksort($inventoryUpdates);
|
||||||
|
|
||||||
// 批量更新
|
// 批量更新
|
||||||
foreach ($inventoryUpdates as $giftId => $count) {
|
foreach ($inventoryUpdates as $giftId => $count) {
|
||||||
$ret = db::name("vs_gift_bag_detail")->where('id',$giftId)->setDec('remaining_number', $count);
|
$ret = db::name("vs_gift_bag_detail")->where('id',$giftId)
|
||||||
|
->lock(true) // 添加悲观锁
|
||||||
|
->setDec('remaining_number', $count);
|
||||||
if (!$ret) {
|
if (!$ret) {
|
||||||
Log::record('巡乐会更新礼物剩余数量: ' . $room_id."【数据】".var_export($precomputedResults, true),"info");
|
Log::record('巡乐会更新礼物剩余数量: ' . $room_id."【数据】".var_export($precomputedResults, true),"info");
|
||||||
throw new \Exception('更新礼物剩余数量失败');
|
throw new \Exception('更新礼物剩余数量失败');
|
||||||
@@ -578,6 +606,15 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
*/
|
*/
|
||||||
private function deductUserCoins($user_id, $bagGiftPrice, $room_id)
|
private function deductUserCoins($user_id, $bagGiftPrice, $room_id)
|
||||||
{
|
{
|
||||||
|
// 使用悲观锁查询用户钱包
|
||||||
|
$userWallet = db::name('user_wallet')
|
||||||
|
->where(['user_id' => $user_id])
|
||||||
|
->lock(true)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$userWallet || $userWallet['coin'] < $bagGiftPrice) {
|
||||||
|
throw new \Exception('用户金币不足');
|
||||||
|
}
|
||||||
$walletUpdate = model('GiveGift')->change_user_cion_or_earnings_log(
|
$walletUpdate = model('GiveGift')->change_user_cion_or_earnings_log(
|
||||||
$user_id,
|
$user_id,
|
||||||
$bagGiftPrice,
|
$bagGiftPrice,
|
||||||
|
|||||||
Reference in New Issue
Block a user