mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
[Feature request] On final flush event. #5770
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @d-ph on GitHub (Nov 14, 2017).
Hello,
I have a very specific use case.
Imagine a function, that creates an entity and immediately flushes it with
$em->flush($theNewEntity);. This function can be called from anywhere in the code. Recently I found out, that I need to call this function from some postUpdate listeners. That causes a problem for me, because the flush of the new entity must happen immediately, otherwise there's a race condition (I won't go into details here).Point being,
EntityManager::flush()es, happening in postUpdate listeners, are not actually flushed. They start a db transaction in an already running db transaction, and then commit the second-level transaction (so, e.g. I have the ID of the new entity), but it's not yet visible in the database at that point (because the "master transaction commit" happens slightly later).In the nutshell, it looks like this:
$em->flush($newSpecialEntity)(this is where the race condition happens)
I thought, that I'd listen on the postFlush event, but unfortunately this one is called first for the second-level transaction and then for the first-level transaction, and I have no way to tell which is which. I tried to determine that from the
$em->getUnitOfWork(), but had some problems with that, because the only difference in the UnitOfWork is the content of theUnitOfWork::$entityChangeSets, which is private and there's no getter for it.As a workaround, I currently listen on both the onFlush and postFlush events and count the occurrence of them. Essentially I take advantage of the fact, that these 2 events are called in the following order:
The pseudo code for the workaround:
It's not very pretty and internal doctrine implementation dependant.
Would it be possible to introduce an event, that's emitted on postFinalFlush, please? When this event is called, end devs should be able to assume, that the enities are definitelly flushed in the database, so they can run their custom logic safely then.
Thank you,
@d-ph
@fesor commented on GitHub (Nov 14, 2017):
Please note that
flush($entity)will not be available as for Doctrine3, it should be replaced by table gateway (#5550).You could just check transaction nesting level:
This isn't race condition.
If you don't have dependencies from updated entities, you could just use another entity manager instance with separate connection in order to start another transaction and have immediate result in database.
If you have dependency from this entity, then you may consider to fire action on
postFlush, notpostUpdateto start brand new transaction (or you could use something like domain events).@d-ph commented on GitHub (Nov 16, 2017):
Hi,
Thanks for the reply.
Thanks for letting me know, that
::flush($entity)isn't available in Doctrine3 -- I didn't know that. I didn't even know, there are plans to release Doctrine3. Doctrine2 is already perfect to me ;pI didn't know, that DBAL tracks the transaction nesting. I quickly read the code and it looks like something, that will work in my case. Thanks for mentioning this.
Sorry, I should've said "this is where the race condition in my system happens". I shouldn't have mentioned this at all, really, since it's of little significance here.
Thanks for suggesting 2 other approaches. I evaluated them already and they have some downsides in my case. But I'm happy to be checking the transaction nesting level in onFlush, and do my thing then, so that's fine.
I'm closing this ticket now. Thanks again for your help.