简体   繁体   中英

Increment, Decrement, as well as Model::decrement() and Model::increment() not working well in Laravel

Well, I have a kind of weird problem. I am receiving data from an API through POST method. When the request hits the intended route, I get the data from the request then decrement or increment user balance based on the request type.

We have two request types: credit and debit. For debit I decrement the user balance and for credit, I increment the user balance by the amount in the request.

Now the problem is that this is working for almost 99% of the requests but for some requests, the balance is not decremented despite the fact that it is received.

The image below is an example of what I am talking about. The records with a green border are the ones where it works as required, where the amount was decremented as required. The one with the red border is where it failed to decrement even though it recorded the amount. Also below is the code that I am using to do this.

Please help me know where the problem might be in my code or how to do it so that the results are consistent. I was using normal decrement and increment operators but it was working the same way. I decided to try the laravel Model::decrement() and Model::increment() but I am encountering the same error!

public function Debit(){
     $data = json_decode(file_get_contents('php://input'), true);
     $username = $data['Login'];
     $user = User::where('username', $username)->first();
     if(!$user){
       $rivalaoResponse = ["d"=>["ErrorCode"=>-10,"HasErrors"=>true,"Message"=>"InvalidPlayer"]];
       return response()->json($rivalaoResponse);
     }
     $type="debit";
     $userId = $user->id;
     $amount = $data['Amount'];
     $gameId = $data['GameId'];
     $roundId = $data['RoundId'];
     $sequence = $data['Sequence'];
     if($user->decrement('casino_bakiye', $amount)){
       $updatedBalance= $user->refresh()->casino_bakiye;
     if($sequence){
       $game = XpgTransaction::where('gameId', $gameId)
                             ->where('roundId', $roundId)
                             ->where('sequence', $sequence)
                             ->first();
       if(!$game){
         $trxn = new XpgTransaction;
         $trxn->user_id = $userId;
         $trxn ->request=json_encode($data);
         $trxn->type =$type;
         $trxn->casino_balance = (float)$updatedBalance;
         $rivalaoResponse = ["d"=>["Data"=>[(float)$updatedBalance],"ErrorCode"=>0,"HasErrors"=>false,"Message"=>""]];
         
         try {
           return  response()->json($rivalaoResponse);
            } finally {
           $trxn->save();
       }
        
       }
       $rivalaoResponse = ["d"=>["ErrorCode"=>-20,"HasErrors"=>true,"Message"=>"Duplicate transaction"]];
       return response()->json($rivalaoResponse);
     }
     }
     

   }

Database illustration

Well, you are experiencing what is called Race Condition This is a condition where you are doing various transactions and updating different tables at the same time. In doing so, some transactions may run ahead of others hence causing the problem. To solve this problem, there are two things you can do, first, using Laravel Transactions This is where you place all the operations in a transaction then after doing everything, you commit the DB. In this case, I will suggest using transactions alongside pessimistic locking Where when one request is being handled, you lock the table so that no other request will read from it etc. You can read more about pessimistic locking here: Laravel's Pessimistic Locking and here you can find more information on Laravel Transactions : DB: Transactions in Laravel

...
DB::beginTransaction();
$user = User::where('username', $username)->sharedLock()->first();
...
$game = XpgTransaction::where('gameId', $gameId)
                             ->where('roundId', $roundId)
                             ->where('sequence', $sequence)
                             ->sharedLock()->first();
...
 $trxn->save();
DB::commit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM