I am using the beanstalkd task queue in order to postpone some heavy Doctrine operations, but this can be reproduced in any other similar system like RabbitMQ, etc.
Client (producer) side
$entityManager = $this->getDoctrine()->getManager();
$productEntity = new Product();
$productEntity->setData('somedata');
$entityManager->persist($productEntity);
// This method is blocking, right? The execution will not continue until the
// data is inserted into the database
$entityManager->flush();
// At this point the data should be already in the database
// $productEntity->getId() returns a valid auto-incremented integer
// So we pass the job to the task queue, which will be executed immediately in the worker
$beanstalkdService->put(
json_encode([
'command'=>'some:heavy:task',
'product_id' => $productEntity->getId()
)
);
Worker daemon (long running process on the same server)
$entityManager = $this->getDoctrine()->getManager();
while(true){
$job = json_decode($beanstalkd->reserve());
if ($job['command'] === 'some:heavy:task'){
$productEntity = $entityManager->find('\Path\To\Product, $job['product_id']);
}
}
the line
$entityManager->find('\Path\To\Product, $job['product_id']);
returns null
if is executed immediately
HOWEVER
if i add a small delay before its execution, like
sleep(1);
$entityManager->find('\Path\To\Product, $job['product_id']);
then the entity is returned as it is supposed to!
Why the record is not accessible without the delay? Isn't the flush() method blocking, so the execution will not continue unless the record is inserted into the database?