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:
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.