I have a product that is up for grabs. First claim is the first served, but the payment process can take a few seconds to finish and can fail. I am not sure how to approach this.
I am testing with this code, and I am sending two requests one after the other. The first one finishes successfully after the 5 seconds wait. The second one I would want it to wait for the first one to finish and then see that it is claimed already, instead it raises a doctrine lock exception.
$em = $this->getDoctrine()->getManager();
//here I would expect it to wait until the lock is released.
$product = $em->getRepository(Product::class)->find(1);
if($product->getStatus() == Product::STATUS_PENDING){
$em->beginTransaction();
$em->lock($product, LockMode::PESSIMISTIC_READ);
try {
sleep(5);
if($paymentService->handlePayment($product)){
$product->setStatus(Product::STATUS_CLAIMED);
$em->persist($product);
$em->flush();
$em->commit();
}else{
$em->commit(); //to release the lock
//throw payment error
}
} catch (\Exception $e) {
$em->rollback();
throw $e;
}
die("success");
}else{
die("already sold");
}
What is the best approach to this? Thanks!