[Messenger] Add support for "recording" events from entities#28850
[Messenger] Add support for "recording" events from entities#28850Nyholm wants to merge 1 commit intosymfony:masterfrom
Conversation
|
I'm afraid that this listener should be stateful and events should be dispatched on post flush event https://github.com/doctrine/doctrine2/blob/2.7/lib/Doctrine/ORM/UnitOfWork.php#L430 (because Doctrine's transaction may fall) |
9441919 to
305438e
Compare
274e3dd to
5d75022
Compare
|
This PR is rebased and squashed |
|
/cc @sroze |
|
Thank you. I've updated the PR |
src/Symfony/Bridge/Doctrine/Messenger/EventSubscriber/EntityMessageCollector.php
Show resolved
Hide resolved
src/Symfony/Bridge/Doctrine/Messenger/EventSubscriber/EntityMessageCollector.php
Outdated
Show resolved
Hide resolved
|
|
||
| if ($entity instanceof EntityMessageCollectionInterface) { | ||
| foreach ($entity->getRecordedMessages() as $message) { | ||
| $this->messageBus->dispatch($message, [new DispatchAfterCurrentBusStamp()]); |
There was a problem hiding this comment.
What if the message bus throws an exception?
There was a problem hiding this comment.
That will bubble up. But the Doctrine transaction will still be committed.
There was a problem hiding this comment.
So there's a risk some messages will be dispatched while some won't. Not sure if that's an issue yet, just pointing it out.
There was a problem hiding this comment.
Yes, If we dispatch 5 messages and number 2 fails, then the 3 other will never be handled. But that is an issue with the message bus and has nothing to do with this PR.
|
Maybe @weaverryan could have a look? |
sroze
left a comment
There was a problem hiding this comment.
Looks good to me, sorry for the delay 👍.
I imagine you'll PR on DoctrineBundle to enable this listener from a configuration flag?
|
@Nyholm can you squad and push again? We should have Travis & AppVeyer rebuilding this :) |
87444c6 to
692448f
Compare
|
Comments are squashed. I will create a PR to doctrine bundle right away |
|
Nice feature! This should not be in 4.4 ? |
|
What if we avoid leaking events and eliminate the getter on the entity? public function dispatchEvents(callable $dispatcher): void
{
$dispatcher($this->events);
$this->events = [];
} |
|
Hm. Callables makes the stack tree hard to follow. @vudaltsov How would you configure an implementation like this to work with DI? |
|
@Nyholm , this would be almost the same code you use: private function collectEventsFromEntity(LifecycleEventArgs $message): void
{
$entity = $message->getEntity();
if (!$entity instanceof EntityMessageCollectionInterface) {
return;
}
$entity->dispatchEvents(function (iterable $events): void {
foreach ($events as $event) {
$this->messageBus->dispatch($event, [new DispatchAfterCurrentBusStamp()]);
}
});
}As you see, we only need one command method in this case, not query+command. |
|
Also, what if we implement this as a middleware, so that we don't depend on Doctrine here? It could do the same thing as the subscriber after the |
| $this->collectEventsFromEntity($event); | ||
| } | ||
|
|
||
| private function collectEventsFromEntity(LifecycleEventArgs $message) |
There was a problem hiding this comment.
if the method is called collectEventsFromEntity, then it should accept object $entity as argument?
| ]; | ||
| } | ||
|
|
||
| public function postFlush(LifecycleEventArgs $event) |
There was a problem hiding this comment.
This code will fail.
The postFlush event is not a lifecycle event. It passes an instance of Doctrine\ORM\Event\PostFlushEventArgs which is not a subclass of LifecycleEventArgs. See https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/events.html#postflush .
There was a problem hiding this comment.
So this event cannot be used here at all, because at this point you do not know which entities were flushed.
|
Im closing this in favor of #34310 |
This is dependent of #28849.