When a RetryableException is thrown, entitymanager should not be closed
When a RetryableException is thrown, entitymanager should not be closed
The "bad" code is here : https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php#L400
RetryableException are DeadlockException and LockWaitTimeoutException
entitymanager should not be closed so we can retry the flush like that
/*
* Since doctrine 2.6, you cannot retry a flush when an exception had appeared
* because the entity manager is closed and all entities detach, even with a RetryableException.
* This function won't work, bescause if there is an Exception, the em is closed.
private retryflush() {
$retry = 0;
while ($retry < 3) {
try {
$this->em->flush();
return;
} catch (RetryableException $e) {
if ($retry >= 2) {
throw $e;
}
sleep(1);
$this->reset();
$retry++;
}
}
}
*/
Is there a good approach to retrying after deadlocks in the meantime?
Is there any "at least not so bad" and simple/quick solution before v3.x release?
For example, i have merge in loop and then make one flush with hundreds entities. But if there is any exception inside of loop – a lot of changes inside loop are lost with log flooded by "EntityManager is closed". That's annoying.
Any solutions can be done here now except making flush/reset inside of loop (super bad idea) or level down to detach from orm and use raw dbal/sql queries?
Approaches were mentioned in #865, but it still will be an entity manager without persisted entities.
Is there already someone that found a solutions for this because impossible to retry it even when you reset the manager ?
The only solution is to do the full request again in rabbitMQ till it's working.
Is there already someone that found a solutions for this because impossible to retry it even when you reset the manager ?
The only solution is to do the full request again in rabbitMQ till it's working.
I wrote entity manager that can do this https://gist.github.com/Rixafy/82d96712cf1f87ce26ce052ced2eba78.
I did it by copying UnitOfWork before flush() or wrapInTransaction is called on real EM, then when RetryableException is thrown, I'll check if EM is closed, and if it is, I'll reopen it using reflection and set the original copy of UnitOfWork, because closing EM also cleared unit of work state, so far it's working alright, I had 2 deadlocks today and both succeeded on 2. attempt.