Add pessimistic locking for job order processing

This commit is contained in:
Kendrick Chan 2018-02-04 18:49:16 +08:00
parent 5c306c1723
commit 006db8a286
2 changed files with 56 additions and 35 deletions

View file

@ -22,6 +22,9 @@ use App\Service\InvoiceCreator;
use App\Service\MapTools;
use Doctrine\ORM\Query;
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\PessimisticLockException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@ -271,22 +274,57 @@ class JobOrderController extends BaseController
{
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
// TODO: check if anyone is already processing
$em = $this->getDoctrine()->getManager();
// TODO: lock and make this user be the processor
$em->getConnection()->beginTransaction();
// TODO: throw error if unable to lock (means someone already locked it before us)
try
{
// lock and get data
$obj = $em->getRepository(JobOrder::class)->find($id, LockMode::PESSIMISTIC_READ);
// make sure this job order exists
if (empty($obj))
{
$em->getConnection()->rollback();
throw $this->createNotFoundException('The job order does not exist');
}
// check status
if ($obj->getStatus() != JOStatus::PENDING)
{
$em->getConnection()->rollback();
throw $this->createNotFoundException('The job order does not have a pending status');
}
// check if we are the processor
$processor = $obj->getProcessedBy();
$user = $this->getUser();
// TODO: go back to list page and display alert / flash that says they cannot access it because they
// are not the processor
if ($processor != null && $processor->getID() != $user->getID())
{
$em->getConnection()->rollback();
throw $this->createAccessDeniedException('Not the processor');
}
// make this user be the processor
$obj->setProcessedBy($user);
$em->flush();
$em->getConnection()->commit();
}
catch(PessimisticLockException $e)
{
throw $this->createAccessDeniedException('Not the processor');
}
// NOTE: we are able to lock, everything should be fine now
$params = $this->initParameters('jo_proc');
$params['mode'] = 'update-processing';
// get row data
$em = $this->getDoctrine()->getManager();
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// get parent associations
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
@ -341,7 +379,12 @@ class JobOrderController extends BaseController
{
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
// TODO: check if we're the one processing, return error otherwise
// check if we're the one processing, return error otherwise
if ($processor == null)
throw $this->createAccessDeniedException('Not the processor');
if ($processor != null && $processor->getID() != $user->getID())
throw $this->createAccessDeniedException('Not the processor');
// initialize error list
$error_array = [];
@ -406,9 +449,9 @@ class JobOrderController extends BaseController
], 422);
}
// TODO: unlock job order and set version to 0, so someone else can modify it
// unlock job order and set version to 0, so someone else can modify it
// NOTE: we don't touch processed_by since we're the one who processed it
$obj->setVersion(0);
// validated! save the entity
$em->flush();

View file

@ -164,15 +164,6 @@ class JobOrder
// invoice
protected $invoice;
// version for optimistic locking
// this will intiially be set to 0 then modified to be the id of the user that locks it
// so only the user can update the entity
/**
* @ORM\Version
* @ORM\Column(type="integer")
*/
protected $version;
public function __construct()
{
$this->date_create = new DateTime();
@ -180,8 +171,6 @@ class JobOrder
$this->flag_advance = false;
$this->source = 'mobile';
$this->version = 0;
}
public function getID()
@ -408,15 +397,4 @@ class JobOrder
{
return $this->delivery_address;
}
public function setVersion($version)
{
$this->version = $version;
return $this;
}
public function getVersion()
{
return $this->version;
}
}