Hi I have a following scenario,
There is two seperate application
ShopManagament - This handle the registration of shop. Contaning aggregate
Shop and other aggregates
NotifyService - This send the mail , sms , notification. Contaning aggregate Email
, SMS , Nofication
The both application build using CQRS/ES with DDD.
Technology used to build the application is Spring with Axon and for messaging usign RabbitMQ
Step 1 -
A shop is registered by issue a command ShopRegisrtraionCommand (ofcourse this handle by the shop aggregate and change the status when event is fired) ,
which fire an event ShopRegistratedEvent .
Step 2 -
When shop ShopRegistredEvent is fired , then I have a EventHandler which listen ShopRegistredEvent and
send the SendEmailVerificationCommand (you can say a request or it act as request )to NotifyService.
Step 3 -
The same command (SendEmailVerificationCommand ) is also handle by the Shop aggregate and
then shop aggregates fire an event MailVerifcationSendedEvent,
this event changes the verification status of Shop to "MailInSendingProcess".
Step 4 -
On other side NotifyService handle that command (SendEmailVerificationCommand or request ) and send the mail ,
if the email successfully sent then NotifyService fire a VerificationEmailSent.
Step 5 -
VerificationEmailSentEvent (fired by NotifyService) is listen by ShopManagment Application using the event listener ,
then this event listener issue a VerificationMailSendedSuccesfullyCommand for the shop aggregates,
and then shop aggregate fire an event VerificationEmailDeliveredEvent , this changes the verifcation status "MailDelivered".
Step 6 -
If the mail sending failed due to any reasons , NotifyService fire another event VerificationEmailSendingUnsuccessfullEvent
which handle by ShopManagament event listener and issue a another command VerificationEmailUnsuccessfull to shop aggregate and then shop
aggregate fire an event VerficationMailSendingFailedEvent , this event change the status of verification status to "MailSendingFalied".
Here the two BC communicate using request and event.
Question -
Can we send command to other bounded context as I am sending in my application or there is another approach.
Is the tracking the status of the Email sending is part of Shop aggregate or I have to create the another aggregate like EmailVerifcation
because I have to resend the falied mail using the schedular.
Is any other way to manage this type of thing if happinning?
I have seen this back and forth between services for verification happen before, but it is typically a process I'd prefer to avoid. It requires intricate teamwork with services for something relatively simple; the intricacy will typically cause pain in the future.
Now to answering your questions:
This should be fine I'd say. A Command is nothing more then a form of message, just like queries or the events in your system. The downside might be that the command-sending Bounded Context should be aware of the 'language' the other Bounded Context speaks. Some form of anti corruption layer might be in place here. See of this as a service which receives the command-sending request of BC-1 in its language and translates it to the language of BC-2. From an Axon Framework perspective I'd also recommend to setting up the DistributedCommandBus, as it contains a component (the CommandRouter to be precise) which is aware of what commands which node might handle.
& 3. This wholly depends on how your domain is modeled. On face value, I'd say a Shop aggregate typically isn't aware of any emails being sent, so from that end I'd say 'no, don't include it in the aggregate'. A Saga would likely be a better fit to send a command to your NotifyService. That Saga would listen to the ShopRegistredEvent and as a response would publish the SendEmailVerificationCommand to the NotifyService. The Saga is able to either act on the callback of the SendEmailVerificationCommand or handle the VerificationEmailSentEvent and VerificationEmailSendingUnsuccessfullEvent to perform the required follow up logic after a (un)successful email.
Hope this gives you some insights Ashwani!
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
We have a microservices architecture to support a big application. All the services communicate using azure service bus as a medium. Currently, we are sending the notifications(immediate/scheduled) from different services on per need basis. Here comes the need for a separate notifications service that could take that load and responsibility of formatting and sending notifications(email, text etc).
What I have thought:
Notification service will have its own database which will have data related to notifications(setup, templates, schedules etc) and also some master data(copied from other sources). I don't want to copy all the transactional data to this DB(for abvious reasons) but we might need transactional and historic data to form a notification. I am planning to subscribe to service bus events (published by other services) and onus of sending the data needed for formatting the notification will be on service raising the service bus event. Notification service will rely on that data to fill up the template(stored in ots own DB) and then send the notification.
Job of notifications service will be to listen to service bus events and then fill up the template from data in event and then send the notification.
Questions:
What if the data received by notification service from service bus event does not have all necessary data needed in notification template. How do I query/get the missing data from other service.?
Suppose a service publishes 100 events for a single operation and we need to send single notification that that whole operation. How does the notification service manage that since it will get 100 different messages separately.?
Since the notification trigger depends on data sent from other sources(service bus event), what happens when we have a notification which is scheduled(lets say 6am everyday). How do we get the data needed for notification(since data is not there in notification DB)?
I am looking for some experience advice and some material to refer. Thanks in advance.
You might have to implement a notification as a service which means, imagine you are exporting your application as a plugin in Azure itself. few points here.....
your notification will only accept when it is valid information,
Have a caching system both front end(State management) and backend, microservices(Redis or any caching system)
Capture EventId on each operation, it's a good practice we track the complex operation of our application in this way you can solve duplicate notification, take care that if possible avoid such type of notifications to the user, or try to send one notification convening a group of notifications in one message,
3.Put a circuit breaker logic here to handle your invalid notification, put this type of notification in the retry queue of 30mins maybe? and republish the event again
References
https://www.rabbitmq.com/dlx.html
https://microservices.io/patterns/reliability/circuit-breaker.html
https://redis.io/topics/introduction
Happy coding :)
In microservice and domain driven design it's sometimes hard to work out when to start splitting services. Having each service be responsible for construction and sending its own notifications is perfectly valid.
It is when there is a need to have additional decisions be made, that are not related to the 'origin' service, where things become more tricky.
EG. 1
You have an order microservice that sends an email to the sales team and the user when an order is placed.
Then the payment service updates sales and the user with an sms message when the payment is processed.
You could then decide you and the user to manage their notification preferences. They can now decide if they want sms / email / push message, and which messages they would like to receive.
We now have a problem. These notification prefrences would need to be understood by every service sending messages. Any new team or service that starts sending messages needs to also remember to implement these preferences.
You may also want the user to view all historic messages they have been sent. Again you get into a problem where there is no single source for that information.
EG 2
We now have notification service, it is listening for order created, order updated, order completed events and payment processed events.
It is listing for:
Order Created
Order Updated
Only to make sure it has the information it needs to construct the messages. It is common and in a lot of requirements to have system wide redundancy of data when using microservices. You need to imagine that each service is an island, so while it feels wasteful to store that information again, if it is required that service to perform is work then it is valid.
Note: don't store the data wholesale, store only what is relevant for that service.
We can then use the:
Order Complete
Payment Processed
events as triggers to actually start constructing and sending the messages.
Problems:
Understanding if the service has all the required data
This is up to the service to determine. If the Order Complete event comes through, but it has not yet received an order created event, then the service should store the order complete event and try to process again in the future when all the information is available.
100 events resulting in a notification
Data aggregation is also an important microservice concept, and there are many ways to ensure completeness that will come down to your specific use case.
I am working on a backend and try to implement CQRS patterns.
I'm pretty clear about events, but sometimes struggle with commands.
I've seen that commands are requested by users, or example ChangePasswordCommand. However in implementation level user is just calling an endpoint, handled by some controller.
I can inject an UserService to my controller, which will handle domain logic and this is how basic tutorials do (I use Nest.js). However I feel that maybe this is where I should use command - so should I execute command ChangePasswordCommand in my controller and then domain module will handle it?
Important thing is that I need return value from the command, which is not a problem from implementation perspective, but it doesn't look good in terms of CQRS - I should ADD and GET at the same time.
Or maybe the last option is to execute the command in controller and then emit an event (PasswordChangedEvent) in command handler. Next, wait till event comes back and return the value in controller.
This last option seems quite good to me, but I have problems with clear implementation inside request lifecycle.
I base on
https://docs.nestjs.com/recipes/cqrs
While the answer by #cperson is technically correct, I would like to add a few nuances to it.
First something that may not be clear from the answer description where it advises to "emit an event (PasswordChangedEvent) in command handler". This is what I would prefer as well, but watch out:
The Command is part of the infrastructure layer, and the Event is part of the domain.
So from the command you should trigger code on the AggregateRoot that emits the event.
This can be done with mergeObjectContext or eventBus.publish (see the NestJS docs).
Events can be applied from other domain objects, but the aggregate usually is the emitter (upon commit).
The other point I wanted to address is that an event-sourced architecture is assumed, i.e. applying CQRS/ES. While CQRS is often used in combination with Event Sourcing there is nothing that prescribes doing so. Event Sourcing can give additional advantages, but also comes with significant added complexity. You should carefully weigh the pros and cons of having ES.
In many cases you do not need Event Sourcing. Having just CQRS already gives you a lot of benefits, such as having your domain / bounded contexts well-contained. Separation between reads and writes, single-responsibility commands + queries (more SOLID in general), cleaner architecture, etc. On a higher level it is easier to shift focus from 'how do I implement this (CRUD-wise)?', to 'how do these user requirements fit in the domain model?'.
Without ES you can have a single relational database and e.g. persist using TypeORM. You can persist events, but it is not needed. In many scenario's you can avoid the eventual consistency where clients need to subscribe to events (maybe you just use them to drive saga's and update read-side views/projections).
You can always start with just CQRS and add Event Sourcing later, when the need arises.
As your architecture evolves, you may find that you require a command bus if you are using Processes/Sagas to manage workflows and inter-aggregate communication. If and when that is the case, it will naturally make sense to use that bus for all commands.
The following is the method I would prefer:
execute the command in controller and then emit an event (PasswordChangedEvent) in command handler. Next, wait till event comes back and return the value in controller.
As for implementation details, in .NET, we use a SignalR websockets service that will read the event bus (where all events are published) and will forward events to clients that have subscribed to them.
In this case, the workflow would be:
The user posts to the controller.
The controller appends the command to the command bus.
The controller returns an ID identifying the command.
The client (browser client) subscribes to events relating to this command.
The command is received by the domain service and handled. An event is emitted to the event store.
The event is published to the event bus.
The event listener subscription service receives the event, finds the subscription, and sends the event to the client.
The client receives the event and notifies the user.
How to design asyn flows in Lagom ?
Problem faced: In our product we have a Lead Aggregate which has a User Id (represents the owner of the lead), Now User has a limitation which says one user can have max of 10 Lead associated with this. We designed this by creating a separate Service ResourceManagement and when a User asks for Picking a Lead, we send a Command to LeadAggregate which generates a Event LeadPickRequested. On ProcessManager Listen to the event and asks for the Resource From ResourceManagement, on Success send Command to LeadAggregate - MarkAsPicked and on this send Push notification to the User that Lead is Picked but from building the UI perspective its very difficult and same cannot be done for exposing our API to third party.
One Sol. we have done is when request is received on Service save a RequestID Vs Request Future . in Command Add the request Id and when the LeadAggregate finally change into Picked State or Picked Failure a PM listen to the event , checks if a RequestFuture is there for the request Id , then complete the future with correct response. This way it works as Sync API for the end User.
Any Better Sol. for this
If you want to provide a synchronous API, I only see two options:
Design your domain model so that Lead creation logic, the "10 leads max" rule and the list of leads for a user are co-located in the same Aggregate root (hint: an AR can spawn another AR).
Accept to involve more than one non-new Aggregate in the same transaction.
The tradeoff depends on transactional analysis about the aggregates in question - will reading from them in the same transaction lead to a lot of locking and race conditions?
I've have a couple of questions to which I am not finding any exact answer. I've used CQRS before, but probably I was not using it properly.
Say that there are 5 services in the domain: Gateway, Sales, Payments, Credit and Warehouse, and that during the process of a user registering with the application, the front-end submits a few commands, the same front-end will then, once the user is registered, send a few other commands to create an order and apply for a credit.
Now, what I usually do is create a gateway, which receives all pubic commands, which are then validated, and if valid, are transformed into domain commands. I only use events to store data and if one service needs some action to be performed in other service, a domain command is sent directly from one service to the other. But I've seen in other systems that event handlers are used for more than store data. So my question is, what are the limits to what event handlers can do? And is it correct to send commands between services when a specific service requires that some other service performs an action or is it more correct to have the initial event raise and event and let the handler in the other service perform that action in the event handler. I am asking this because I've seen events like: INeedCreditAproved, when I was hoping to see a domain command like: ApprovedCredit.
Any input is welcome.
You're missing an important concept here - Sagas (Process Managers). You have a long-running workflow and it's better expressed centrally.
Sagas listen to events and emit commands. So OrderAccepted event will start a Saga, which then emit ApproveCredit and ReserveStock commands, to be sent to Credit and Warehouse services respectively. Saga can then listen to command success/failure events and compensate approprietely, like say emiting SendEmail command or whatever else.
One year ago I was sending commands like "send commands between services by event handlers when a specific service requires that some other service performs an action" but a stupid decision made by me switched to using events like you said "to have the initial event raise and event and let the handler in the other service perform that action in the event handler" and it worked at first. The most stupid decision I could make. Now I am switching back to sending commands from event handlers.
You can see that other people like Rinat do similar things with event ports/receptors and it is working for them, I think:
http://abdullin.com/journal/2012/7/22/bounded-context-is-a-team-working-together.html
http://abdullin.com/journal/2012/3/31/anatomy-of-distributed-system-a-la-lokad.html
Good luck
I'm new to DDD and I'm reading articles now to get more information. One of the articles focuses on domain events (DE). For example sending email is a domain event raised after some criteria is met while executing piece of code.
Code example shows one way of handling domain events and is followed by this paragraph
Please be aware that the above code will be run on the same thread within the same transaction as the regular domain work so you should avoid performing any blocking activities, like using SMTP or web services. Instead, prefer using one-way messaging to communicate to something else which does those blocking activities.
My questions are
Is this a general problem in handling DE? Or it is just concern of the solution in mentioned article?
If domain events are raised in transaction and the system will not handle them synchronously, how should they be handled?
When I decide to serialize these events and let scheduler (or any other mechanism) execute them, what happens when transaction is rolled back? (in the article event is raised in code executed in transaction) who will cancel them (when they are not persisted to database)?
Thanks
It's a general problem period never mind DDD
In general, in any system which is required to respond in a performant manner (e.g. a Web Server, any long running activities should be handled asynchronously to the triggering process.
This means queue.
Rolling back your transaction should remove item from the queue.
Of course, you now need additional mechanisms to handle the situation where the item on the queue fails to process - i.e the email isn't sent - you also need to allow for this in your triggering code - having a subsequent process RELY on the earlier process having already occurred is going to cause issues at some point.
In short, your queueing mechanism should itself be transactional and allow for retries and you need to think about the whole chain of events as a workflow.