orm icon indicating copy to clipboard operation
orm copied to clipboard

When a RetryableException is thrown, entitymanager should not be closed

Open kcassam opened this issue 8 years ago • 5 comments

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++;
            } 
        }
    }
*/

kcassam avatar Feb 01 '17 15:02 kcassam

Is there a good approach to retrying after deadlocks in the meantime?

jaikdean avatar Aug 09 '19 10:08 jaikdean

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?

tinpansoul avatar Oct 11 '19 14:10 tinpansoul

Approaches were mentioned in #865, but it still will be an entity manager without persisted entities.

SenseException avatar Oct 15 '19 20:10 SenseException

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.

dvdknaap avatar Oct 06 '21 10:10 dvdknaap

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.

rixafy avatar Feb 23 '25 11:02 rixafy