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!