Search code examples
phpmysqllaravelvotingvoting-system

Voting system that being run at the same time not all saved


so i am working at voting system that have code like this

public function storeVote(Request $request)
    {   
        $voting = Voting::findOrFail($request->voting_id);

        if($voting->status == 1){
            $checkVote = vote::where('voting_id',$request->voting_id)->where('name',$request->name)->where('voting_candidate_id',null)->first();
    
            if($checkVote){
                \DB::beginTransaction(); 
                try{
                    $candidate = candidate::findOrFail($request->voting_candidate_id);
                    $skor = $candidate->skor + 1;
                    $candidate->skor = $skor;
                    $candidate->update();
            
                    $checkVote->voting_candidate_id = $request->voting_candidate_id;
                    $checkVote->update();
    
                    $vote_ok = $voting->vote_ok + 1;
                    $voting->vote_ok = $vote_ok;
                    $voting->update();
                    
                    event(new VotingEvent($skor, $voting->id, $candidate->id));

                    CandidateProfile::flushCache();
                    
                    \DB::commit();
                    return response()
                        ->json([
                            'saved' => true,
                            'message' => 'Voting done.',
                        ]); 
                } catch (\Exception $e){
                    \DB::rollBack();
                    abort(500, $e->getMessage());
                }
            }else{
                return response()
                    ->json([
                        'saved' => false,
                        'message' => 'sorry, you already vote'
                    ]); 
            }
        }else{
            return response()
                    ->json([
                        'saved' => false,
                        'message' => 'Sorry, Voting session not started yet'
                    ]);
        }
    }

so this function act as a way for user to vote, the participant have a unique link where they only need to choose the candidate and then it will be trigger the function above

the problem is when i tested to do like 30 vote at the same time, half of them not saved.

any idea why?

update: the data that are not saved:

  1. candidate skor is not updated or not multiplied
  2. voting information about vote_ok which mean total vote that being use

Solution

  • Note there is a catch when you use update queries. For eg: in you above code you are updating the candicate_skor using;

    $skor = $candidate->skor + 1;
    $candidate->skor = $skor;
    $candidate->update();
    

    The problem arises when your server gets multiple concurrent requests for the same route. For each of the requests (let's say you have 5 requests) the function retrieves the old candidate_skore value let's say it was equal to 1. Now when each of them updates the value DB value it will be equal to 2. Even though you have 5 upvote requests that should update the DB value to 6 it updates to just 2, causing you to lose 4 votes.

    Ideally, you should keep a relation table for all the votes received and only insert it into that relation table. That way even if simultaneous requests are served all of them will insert new entries to the table. Finally, your total vote should be equal to the count of all rows in that relation table.