Closed mxkh closed 3 years ago
Hi @mxkh
Your approach makes totally sense to me in terms of workflow.
An event listener class / interface
that implements/extends
Broadway\EventHandling\EventListener
in your domain layer and the implementation for the transport (mail, push, sms...) in infrastructure. Keep in mind I use Broadway and method to implement here is handle
instead __invoke
as you may expect but there're a reason and it's in the read model event handling side: https://github.com/broadway/broadway/blob/master/src/Broadway/ReadModel/Projector.php#L36
Happy to add more advanced examples and improve documentation. Open for suggestions 👍
The component Messenger of Symfony isn't sufficient ? Because it do that no ?
@xfifix the messenger component is used for the Command
, Query
and AsyncEventBus
but Broadway has his own even bus too but ONLY for synchronous tasks. So yes, you're right and I miss the topic here that if you want to to this in an async way you've to implement this interface and will be automatically executed in the workers
That' makes me realise there's a lot of room for improvement in the documentation. Thanks!
@jorge07 Thanks for your reply! It was helpful!
So, if I want to send a notification, where should I do that according to your boilerplate? I want to clarify how to use it properly. Should I work with the read model events? Because I want to make sure that the persistence layer finished successfully and only then send UserWasCreated
notification to some transport
You've an aggregate root called User, when the user is created it generates a UserWasCreated event. Then it get persisted in the write model (events gets persisted). Then this event it's published in the event bus and you've some projections, like the UserView in this repo, that generates the read model. This projection handlers extend Broadway Projection so they will be executed synchronously. You can put your SMS handler on the async event bus to guarantee it gets executed when read model is already applied. Otherwise you'll need to deal with eventual consistency
You've an aggregate root call User, when the user is created it generates a UserWasCreated event. Then it get persistent in the write model (events gets persisted). Then this event it's published in the event bus and you've some projections like the UserView in this repo that generates the read model. This projection handlers extend Broadway Projection so they will be executed synchronously. You can put your SMS handler on the async event bus to guarantee it gets extended when read model is already applied. Otherwise you'll need to deal with eventual consistency
Thanks for the detailed answer! Your words confirm what I was thinking about but I wanted to get proof of my thoughts 😅 Thank you a lot! I am going to fork your boilerplate and add more examples.
Lolz I realized how poorly written was my response, sorry, I was walking with the kid and the autofixes in the phone keyboard doesn't behave very well with Spanish and English languages enabled at the same time
I'm refactoring few things and playing with advance things with symfony messenger. It's all in #187 PR There's an example of how to deal with async events here with some notes about the things i found and work around https://github.com/jorge07/symfony-5-es-cqrs-boilerplate/pull/187/files#diff-7a5e0582aaf2f0e794df52345439b794
Hi @jorge07!
Your boilerplate is fantastic! I have a question regarding the domain operations.
For example, after
UserWasCreated
, who should be responsible for sending a notification (email, push, SMS) after the persistence layer successfully finished his work? Should we have theHandler
class that will work with the event bus as a part of the domain layer, which will expect theUserWasCreated
event in the__invoke
method? I spied this approach in botilka demoAlso, it would be nice to add more advanced examples to the boilerplate. Currently, I am working on investigating DDD for my organization and I might contribute if you don't mind.
Thanks!