fix: 规范数据库事物的使用,解决在swoole环境下可能会出现事物一直不被提交的问题

This commit is contained in:
xboard 2023-12-06 19:00:26 +08:00
parent 64cc2d79da
commit 1fcb6fa911
13 changed files with 293 additions and 251 deletions

View File

@ -64,6 +64,7 @@ class CheckCommission extends Command
->where('invite_user_id', '!=', NULL) ->where('invite_user_id', '!=', NULL)
->get(); ->get();
foreach ($orders as $order) { foreach ($orders as $order) {
try{
DB::beginTransaction(); DB::beginTransaction();
if (!$this->payHandle($order->invite_user_id, $order)) { if (!$this->payHandle($order->invite_user_id, $order)) {
DB::rollBack(); DB::rollBack();
@ -75,6 +76,10 @@ class CheckCommission extends Command
continue; continue;
} }
DB::commit(); DB::commit();
} catch (\Exception $e){
DB::rollBack();
throw $e;
}
} }
} }

View File

@ -2,11 +2,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Helpers\ApiResponse;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController class Controller extends BaseController
{ {
use DispatchesJobs, ValidatesRequests; use DispatchesJobs, ValidatesRequests, ApiResponse;
} }

View File

@ -87,6 +87,7 @@ class CouponController extends Controller
$coupon['code'] = Helper::randomChar(8); $coupon['code'] = Helper::randomChar(8);
array_push($coupons, $coupon); array_push($coupons, $coupon);
} }
try{
DB::beginTransaction(); DB::beginTransaction();
if (!Coupon::insert(array_map(function ($item) use ($coupon) { if (!Coupon::insert(array_map(function ($item) use ($coupon) {
// format data // format data
@ -98,10 +99,14 @@ class CouponController extends Controller
} }
return $item; return $item;
}, $coupons))) { }, $coupons))) {
DB::rollBack();
throw new ApiException(500, '生成失败'); throw new ApiException(500, '生成失败');
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
$data = "名称,类型,金额或比例,开始时间,结束时间,可用次数,可用于订阅,券码,生成时间\r\n"; $data = "名称,类型,金额或比例,开始时间,结束时间,可用次数,可用于订阅,券码,生成时间\r\n";
foreach($coupons as $coupon) { foreach($coupons as $coupon) {
$type = ['', '金额', '比例'][$coupon['type']]; $type = ['', '金额', '比例'][$coupon['type']];

View File

@ -77,18 +77,18 @@ class KnowledgeController extends Controller
public function sort(KnowledgeSort $request) public function sort(KnowledgeSort $request)
{ {
DB::beginTransaction();
try { try {
DB::beginTransaction();
foreach ($request->input('knowledge_ids') as $k => $v) { foreach ($request->input('knowledge_ids') as $k => $v) {
$knowledge = Knowledge::find($v); $knowledge = Knowledge::find($v);
$knowledge->timestamps = false; $knowledge->timestamps = false;
$knowledge->update(['sort' => $k + 1]); $knowledge->update(['sort' => $k + 1]);
} }
DB::commit();
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollBack(); DB::rollBack();
throw new ApiException(500, '保存失败'); throw new ApiException(500, '保存失败');
} }
DB::commit();
return response([ return response([
'data' => true 'data' => true
]); ]);

View File

@ -156,6 +156,7 @@ class OrderController extends Controller
throw new ApiException(500, '该用户还有待支付的订单,无法分配'); throw new ApiException(500, '该用户还有待支付的订单,无法分配');
} }
try {
DB::beginTransaction(); DB::beginTransaction();
$order = new Order(); $order = new Order();
$orderService = new OrderService($order); $orderService = new OrderService($order);
@ -178,11 +179,13 @@ class OrderController extends Controller
$orderService->setInvite($user); $orderService->setInvite($user);
if (!$order->save()) { if (!$order->save()) {
DB::rollback();
throw new ApiException(500, '订单创建失败'); throw new ApiException(500, '订单创建失败');
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
return response([ return response([
'data' => $order->trade_no 'data' => $order->trade_no

View File

@ -118,14 +118,19 @@ class PaymentController extends Controller
'ids.required' => '参数有误', 'ids.required' => '参数有误',
'ids.array' => '参数有误' 'ids.array' => '参数有误'
]); ]);
try{
DB::beginTransaction(); DB::beginTransaction();
foreach ($request->input('ids') as $k => $v) { foreach ($request->input('ids') as $k => $v) {
if (!Payment::find($v)->update(['sort' => $k + 1])) { if (!Payment::find($v)->update(['sort' => $k + 1])) {
DB::rollBack();
throw new ApiException(500, '保存失败'); throw new ApiException(500, '保存失败');
} }
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
return response([ return response([
'data' => true 'data' => true
]); ]);

View File

@ -50,11 +50,11 @@ class PlanController extends Controller
]); ]);
} }
$plan->update($params); $plan->update($params);
DB::commit();
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollBack(); DB::rollBack();
throw new ApiException(500, '保存失败'); throw new ApiException(500, '保存失败');
} }
DB::commit();
return response([ return response([
'data' => true 'data' => true
]); ]);
@ -104,23 +104,24 @@ class PlanController extends Controller
throw new ApiException(500, '保存失败'); throw new ApiException(500, '保存失败');
} }
return response([ return $this->success();
'data' => true
]);
} }
public function sort(PlanSort $request) public function sort(PlanSort $request)
{ {
try{
DB::beginTransaction(); DB::beginTransaction();
foreach ($request->input('plan_ids') as $k => $v) { foreach ($request->input('plan_ids') as $k => $v) {
if (!Plan::find($v)->update(['sort' => $k + 1])) { if (!Plan::find($v)->update(['sort' => $k + 1])) {
DB::rollBack();
throw new ApiException(500, '保存失败'); throw new ApiException(500, '保存失败');
} }
} }
DB::commit(); DB::commit();
return response([ }catch (\Exception $e){
'data' => true DB::rollBack();
]); throw $e;
}
return $this->success(true);
} }
} }

View File

@ -28,19 +28,21 @@ class ManageController extends Controller
'hysteria', 'hysteria',
'vless' 'vless'
) ?? []; ) ?? [];
try{
DB::beginTransaction(); DB::beginTransaction();
foreach ($params as $k => $v) { foreach ($params as $k => $v) {
$model = 'App\\Models\\Server' . ucfirst($k); $model = 'App\\Models\\Server' . ucfirst($k);
foreach($v as $id => $sort) { foreach($v as $id => $sort) {
if (!$model::find($id)->update(['sort' => $sort])) { if (!$model::find($id)->update(['sort' => $sort])) {
DB::rollBack();
throw new ApiException(500, '保存失败'); throw new ApiException(500, '保存失败');
} }
} }
} }
DB::commit(); DB::commit();
return response([ }catch (\Exception $e){
'data' => true DB::rollBack();
]); throw $e;
}
return $this->success(true);
} }
} }

View File

@ -230,12 +230,16 @@ class UserController extends Controller
$user['password'] = password_hash($request->input('password') ?? $user['email'], PASSWORD_DEFAULT); $user['password'] = password_hash($request->input('password') ?? $user['email'], PASSWORD_DEFAULT);
array_push($users, $user); array_push($users, $user);
} }
try{
DB::beginTransaction(); DB::beginTransaction();
if (!User::insert($users)) { if (!User::insert($users)) {
DB::rollBack();
throw new ApiException(500, '生成失败'); throw new ApiException(500, '生成失败');
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
$data = "账号,密码,过期时间,UUID,创建时间,订阅地址\r\n"; $data = "账号,密码,过期时间,UUID,创建时间,订阅地址\r\n";
foreach($users as $user) { foreach($users as $user) {
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']); $expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);

View File

@ -114,6 +114,7 @@ class OrderController extends Controller
throw new ApiException(500, __('This subscription has expired, please change to another subscription')); throw new ApiException(500, __('This subscription has expired, please change to another subscription'));
} }
try{
DB::beginTransaction(); DB::beginTransaction();
$order = new Order(); $order = new Order();
$orderService = new OrderService($order); $orderService = new OrderService($order);
@ -126,7 +127,6 @@ class OrderController extends Controller
if ($request->input('coupon_code')) { if ($request->input('coupon_code')) {
$couponService = new CouponService($request->input('coupon_code')); $couponService = new CouponService($request->input('coupon_code'));
if (!$couponService->use($order)) { if (!$couponService->use($order)) {
DB::rollBack();
throw new ApiException(500, __('Coupon failed')); throw new ApiException(500, __('Coupon failed'));
} }
$order->coupon_id = $couponService->getId(); $order->coupon_id = $couponService->getId();
@ -141,14 +141,12 @@ class OrderController extends Controller
$userService = new UserService(); $userService = new UserService();
if ($remainingBalance > 0) { if ($remainingBalance > 0) {
if (!$userService->addBalance($order->user_id, - $order->total_amount)) { if (!$userService->addBalance($order->user_id, - $order->total_amount)) {
DB::rollBack();
throw new ApiException(500, __('Insufficient balance')); throw new ApiException(500, __('Insufficient balance'));
} }
$order->balance_amount = $order->total_amount; $order->balance_amount = $order->total_amount;
$order->total_amount = 0; $order->total_amount = 0;
} else { } else {
if (!$userService->addBalance($order->user_id, - $user->balance)) { if (!$userService->addBalance($order->user_id, - $user->balance)) {
DB::rollBack();
throw new ApiException(500, __('Insufficient balance')); throw new ApiException(500, __('Insufficient balance'));
} }
$order->balance_amount = $user->balance; $order->balance_amount = $user->balance;
@ -157,11 +155,13 @@ class OrderController extends Controller
} }
if (!$order->save()) { if (!$order->save()) {
DB::rollback();
throw new ApiException(500, __('Failed to create order')); throw new ApiException(500, __('Failed to create order'));
} }
DB::commit(); DB::commit();
}catch (\Exception $e){
DB::rollBack();
throw $e;
}
return response([ return response([
'data' => $order->trade_no 'data' => $order->trade_no

View File

@ -48,6 +48,7 @@ class TicketController extends Controller
public function save(TicketSave $request) public function save(TicketSave $request)
{ {
try{
DB::beginTransaction(); DB::beginTransaction();
if ((int)Ticket::where('status', 0)->where('user_id', $request->user['id'])->lockForUpdate()->count()) { if ((int)Ticket::where('status', 0)->where('user_id', $request->user['id'])->lockForUpdate()->count()) {
throw new ApiException(500, __('There are other unresolved tickets')); throw new ApiException(500, __('There are other unresolved tickets'));
@ -59,7 +60,6 @@ class TicketController extends Controller
'user_id' => $request->user['id'] 'user_id' => $request->user['id']
])); ]));
if (!$ticket) { if (!$ticket) {
DB::rollback();
throw new ApiException(500, __('Failed to open ticket')); throw new ApiException(500, __('Failed to open ticket'));
} }
$ticketMessage = TicketMessage::create([ $ticketMessage = TicketMessage::create([
@ -68,10 +68,13 @@ class TicketController extends Controller
'message' => $request->input('message') 'message' => $request->input('message')
]); ]);
if (!$ticketMessage) { if (!$ticketMessage) {
DB::rollback();
throw new ApiException(500, __('Failed to open ticket')); throw new ApiException(500, __('Failed to open ticket'));
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
$this->sendNotify($ticket, $request->input('message')); $this->sendNotify($ticket, $request->input('message'));
return response([ return response([
'data' => true 'data' => true
@ -156,6 +159,7 @@ class TicketController extends Controller
if ($limit > ($user->commission_balance / 100)) { if ($limit > ($user->commission_balance / 100)) {
throw new ApiException(500, __('The current required minimum withdrawal commission is :limit', ['limit' => $limit])); throw new ApiException(500, __('The current required minimum withdrawal commission is :limit', ['limit' => $limit]));
} }
try{
DB::beginTransaction(); DB::beginTransaction();
$subject = __('[Commission Withdrawal Request] This ticket is opened by the system'); $subject = __('[Commission Withdrawal Request] This ticket is opened by the system');
$ticket = Ticket::create([ $ticket = Ticket::create([
@ -164,7 +168,6 @@ class TicketController extends Controller
'user_id' => $request->user['id'] 'user_id' => $request->user['id']
]); ]);
if (!$ticket) { if (!$ticket) {
DB::rollback();
throw new ApiException(500, __('Failed to open ticket')); throw new ApiException(500, __('Failed to open ticket'));
} }
$message = sprintf("%s\r\n%s", $message = sprintf("%s\r\n%s",
@ -177,10 +180,13 @@ class TicketController extends Controller
'message' => $message 'message' => $message
]); ]);
if (!$ticketMessage) { if (!$ticketMessage) {
DB::rollback();
throw new ApiException(500, __('Failed to open ticket')); throw new ApiException(500, __('Failed to open ticket'));
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
$this->sendNotify($ticket, $message); $this->sendNotify($ticket, $message);
return response([ return response([
'data' => true 'data' => true

View File

@ -36,16 +36,12 @@ class OrderService
if ($order->refund_amount) { if ($order->refund_amount) {
$this->user->balance = $this->user->balance + $order->refund_amount; $this->user->balance = $this->user->balance + $order->refund_amount;
} }
try{
DB::beginTransaction(); DB::beginTransaction();
if ($order->surplus_order_ids) { if ($order->surplus_order_ids) {
try {
Order::whereIn('id', $order->surplus_order_ids)->update([ Order::whereIn('id', $order->surplus_order_ids)->update([
'status' => 4 'status' => 4
]); ]);
} catch (\Exception $e) {
DB::rollback();
throw new ApiException(500, '开通失败');
}
} }
switch ((string)$order->period) { switch ((string)$order->period) {
case 'onetime_price': case 'onetime_price':
@ -73,16 +69,18 @@ class OrderService
$this->setSpeedLimit($plan->speed_limit); $this->setSpeedLimit($plan->speed_limit);
if (!$this->user->save()) { if (!$this->user->save()) {
DB::rollBack(); throw new \Exception('用户信息保存失败');
throw new ApiException(500, '开通失败');
} }
$order->status = 3; $order->status = 3;
if (!$order->save()) { if (!$order->save()) {
throw new \Exception('订单信息保存失败');
}
DB::commit();
}catch(\Exception $e){
DB::rollBack(); DB::rollBack();
\Log::error($e);
throw new ApiException(500, '开通失败'); throw new ApiException(500, '开通失败');
} }
DB::commit();
} }
@ -233,21 +231,25 @@ class OrderService
public function cancel():bool public function cancel():bool
{ {
$order = $this->order; $order = $this->order;
try {
DB::beginTransaction(); DB::beginTransaction();
$order->status = 2; $order->status = 2;
if (!$order->save()) { if (!$order->save()) {
DB::rollBack(); throw new \Exception('Failed to save order status.');
return false;
} }
if ($order->balance_amount) { if ($order->balance_amount) {
$userService = new UserService(); $userService = new UserService();
if (!$userService->addBalance($order->user_id, $order->balance_amount)) { if (!$userService->addBalance($order->user_id, $order->balance_amount)) {
DB::rollBack(); throw new \Exception('Failed to add balance.');
return false;
} }
} }
DB::commit(); DB::commit();
return true; return true;
}catch(\Exception $e){
DB::rollBack();
\Log::error($e);
return false;
}
} }
private function setSpeedLimit($speedLimit) private function setSpeedLimit($speedLimit)

View File

@ -13,6 +13,7 @@ use Illuminate\Support\Facades\DB;
class TicketService { class TicketService {
public function reply($ticket, $message, $userId) public function reply($ticket, $message, $userId)
{ {
try{
DB::beginTransaction(); DB::beginTransaction();
$ticketMessage = TicketMessage::create([ $ticketMessage = TicketMessage::create([
'user_id' => $userId, 'user_id' => $userId,
@ -25,11 +26,14 @@ class TicketService {
$ticket->reply_status = 1; $ticket->reply_status = 1;
} }
if (!$ticketMessage || !$ticket->save()) { if (!$ticketMessage || !$ticket->save()) {
DB::rollback(); throw new \Exception();
return false;
} }
DB::commit(); DB::commit();
return $ticketMessage; return $ticketMessage;
}catch(\Exception $e){
DB::rollback();
return false;
}
} }
public function replyByAdmin($ticketId, $message, $userId):void public function replyByAdmin($ticketId, $message, $userId):void
@ -40,6 +44,7 @@ class TicketService {
throw new ApiException(500, '工单不存在'); throw new ApiException(500, '工单不存在');
} }
$ticket->status = 0; $ticket->status = 0;
try{
DB::beginTransaction(); DB::beginTransaction();
$ticketMessage = TicketMessage::create([ $ticketMessage = TicketMessage::create([
'user_id' => $userId, 'user_id' => $userId,
@ -52,10 +57,13 @@ class TicketService {
$ticket->reply_status = 1; $ticket->reply_status = 1;
} }
if (!$ticketMessage || !$ticket->save()) { if (!$ticketMessage || !$ticket->save()) {
DB::rollback();
throw new ApiException(500, '工单回复失败'); throw new ApiException(500, '工单回复失败');
} }
DB::commit(); DB::commit();
}catch(\Exception $e){
DB::rollBack();
throw $e;
}
$this->sendEmailNotify($ticket, $ticketMessage); $this->sendEmailNotify($ticket, $ticketMessage);
} }