-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Messenger] add a transport that processes messages on kernel.terminate #28746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
(Deprecation label should be removed BTW) |
src/Symfony/Component/Messenger/Handler/KernelTerminationHandler.php
Outdated
Show resolved
Hide resolved
I think the approach of having a decorated handler might not be the best. What about using a transport for this? |
@sroze Not sure if I got it right....is this the right approach? If it is, I'll create tests, documentation etc. |
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransport.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransport.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransport.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransport.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransport.php
Outdated
Show resolved
Hide resolved
Just for the sake of completeness, here is the whole workflow to me:
I'm just not sure about 4. Perhaps it should be configurable at the transport level as an option. |
@@ -1553,6 +1554,11 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder | |||
->addTag('messenger.receiver', array('alias' => $name)) | |||
->addTag('messenger.sender', array('alias' => $name)) | |||
; | |||
|
|||
if ('symfony://kernel.terminate' === $transport) { | |||
$transportDefinition->addTag('kernel.event_listener', array('event' => KernelEvents::TERMINATE)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you take the event from what is after symfony://
instead of hardcoding it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense if we're only going to listen to that event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments after #28646 (comment).
I'm not convinced another use-case should be provided out-of-the-box by the Framework bundle.
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransport.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/KernelTerminate/KernelTerminateTransportFactory.php
Outdated
Show resolved
Hide resolved
See #28646 (comment) for more thoughts on this. |
I've updated the PR as per the comments (hope I understood all comments correctly...).
|
BTW does anyone have a sandbox project I could use to test this functionality? |
@sroze @nicolas-grekas @ogizanagi Have updated the PR with suggestions given, it's not ready to review yet as it's not complete, but would like some feedback to check if I'm in the right direction before doing the final work. |
@gonzalovilaseca : Sorry for the lack of answer.
I think the factory should be aware of all the available buses, by injecting a service locator. Then, a transport option should allow the factory to select the right bus by its key. |
Can you check what I've done in |
You may have more than one of such transport. For instance one per bus. The factory would be used to create each of these then (so it needs to know every buses). |
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
updated! |
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
@sroze @nicolas-grekas @ogizanagi Are we happy with this as it is, so I can start writing tests? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good (to me) yes :)
...Symfony/Component/Messenger/Transport/KernelTerminate/SymfonyKernelEventTransportFactory.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
Updated! |
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
@gonzalovilaseca: I hope you won't mind me, but I've rebased and pushed some changes to your branch hopefully fixing @sroze's review and some other tweaks I've spotted during this operation :) |
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/KernelTerminateTransportFactory.php
Outdated
Show resolved
Hide resolved
@@ -1568,6 +1576,21 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder | |||
->setArguments(array($transport['dsn'], $transport['options'])) | |||
->addTag('messenger.receiver', array('alias' => $name)) | |||
; | |||
|
|||
if (0 === strpos($transport['dsn'], 'symfony://kernel.terminate')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I just realized this won't work with env vars.
As I don't see any use-cases for it, it may be fine, but we need extra pov.
If we want to support it, the kernel terminate transport factory will need the event dispatcher and add listeners itself (still, that would be a better implementation and give the factory even more sense?).
(Note the same goes for the amqp://
check above, but it's only about a hint for the developper)
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
Show resolved
Hide resolved
@ogizanagi @sroze I've updated the PR with tests |
@gonzalovilaseca : Great! :) But I think we need to treat #28746 (comment). Consistency is the key, this transport dsn should work as an env var as any other. Regarding #29097 (comment), I also think we should extract the re-dispatching logic out of the |
*/ | ||
public function stop(): void | ||
{ | ||
$this->envelopes = array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of emptying, we may just use a $stopped
flag used in receive to skip handling as in
if (!$this->stopped) { |
Can an event be registered at runtime? (I thought that wasnt possible as the container is already compiled) |
Sure. You'll need to inject the |
Ok cool, will do that then. |
… kernel.terminate
@ogizanagi updated following suggestions |
public function flush(): void | ||
{ | ||
$this->receive(function (Envelope $envelope) { | ||
if (null === $envelope) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$envelope
can not be null
here, because of the type hint.
$transport = new MemoryTransport($this->busLocator->get($busId)); | ||
|
||
$this->eventDispatcher->addListener(KernelEvents::TERMINATE, array($transport, 'flush')); | ||
$this->eventDispatcher->addListener(KernelEvents::EXCEPTION, array($transport, 'stop')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we also have to add listeners to the corresponding console events? Like in swiftmailer-bundle for the memory spool?
Any chance to get this merged into 4.3? (feature freeze is in two weeks) |
It's just waiting for review.. |
Thank you very much for your efforts on this pull-request @gonzalovilaseca. Now that we have other transports (Doctrine especially) I think that the risks associated with such transport are too high: as mentioned by @fabpot ealier, running things on Let's close this so we push everybody to use more reliable solutions 🚀 |
Sorry for making you work on this, but even if it wasn't merged, it helped a lot moving things forward! So thank you! |
I'm not sure if this is what Nicolas was asking for in this issue: #28646 (comment)
If it is, there are some questions that need general consensus: