I need to do something basic, I have two entities: User and Action. Each User has X tokens assigned by the Admin and then he can perform Y actions based on the amount of tokens. So lets say one User only has enough tokens to perform one Action, I identified that if I perform multiple simultaneously requests at the same exact time (like 5 or more requests at the same time). Instead of just one Action, the User executes two or more Actions (and only in the explained scenario, in the rest everything works fine)
The related code to my explanation:
public function useractions(Requests $request){
$user = $this->getUser();
$post = Request::createFromGlobals();
if($post->request->has('new_action') && $this->isCsrfTokenValid("mycsrf", $post->request->get('csrf_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$tokens = $user->getTokens();
if($tokens<1){
$error = "Not enough tokens";
}
if(empty($error)){
$user->setTokens($tokens-1);
$entityManager->flush();
$action = new Action();
$action->setUser($user);
$entityManager->persist($transaction);
$entityManager->flush();
}
}
}
And I am using mariadb 10.5.12 with InnoDB as the engine
Obviously I am making a big mistake in my code or missing something in the Symfony or Doctrine configuration. Someone could tell me the mistake? Thanks
My Answer:
> In order to prevent this issue of multiple actions being executed when multiple requests are made simultaneously, you can use database transactions to ensure data consistency.
Here is an example of how you can modify your code to use transactions:
php
public function useractions(Requests $request){
$entityManager = $this->getDoctrine()->getManager();
$user = $entityManager->getRepository(User::class)->find($userId);
$entityManager->beginTransaction();
try {
// Perform the necessary actions here
// Update the user's token count
$user->setTokens($user->getTokens() - 1);
$entityManager->persist($user);
$entityManager->flush();
// Create the action entity
$action = new Action();
$action->setUser($user);
// Set other action properties
$entityManager->persist($action);
$entityManager->flush();
$entityManager->commit();
} catch (\Exception $e) {
$entityManager->rollback();
throw $e;
}
return new Response('Action performed successfully');
}
By using transactions, you can ensure that the updates to the User and Action entities are atomic and consistent, even when multiple requests are made simultaneously. This will help prevent the issue of multiple actions being executed for a user with limited tokens.
Rate this post
3 of 5 based on 5538 votesComments