I have product service, category service, promotions service, search service.
When User want to add product. CreateProductRequest come to product service. Request includes product data and datas of other services like categoryId,uncalculated price , too. After product is added. I need to send other servie datas. Category service needs productId and CategoryId. Promotions service needs productId and price.
After creat eproduct transaction commited;
1) I put all data in ProductCreatedEvent that includes saved productId, categoryId, uncalculated price etc. Every service get what it needs from event and save to own db. I publish event with RabbitMQ
2) Send via seperated commands to services.I send commands with RabbitMQ
And What If there is no category that id come with event and Category services didn't save. But Product saved at product Services ?
or what do you suggest ?
To answer the question, it's important to keep in mind the difference between a command and event. A command is a request to do something. An event is a record of something that has happened. One key difference is that a command can be rejected.
When looking at your use case, publishing events to other services makes the most sense. The product has been created and you are notifying the other bounded contexts that care about the change. If you issue a command, you are telling other bounded context to make a change that may or may not fail.
That said, you each bounded context may receive the event and produce a command within their own context to update aggregates managed within. As such, the difference is subtle between these two:
- Issue a command to each bounded context
- Issue an event to each bounded context and they can then trigger a command as needed
But given the above, the notification of the creation of the product should not fail. It has happened already. From there, each context can decide what to do about it.
Related
I am trying to understand how to implement this in Event sourcing model / DDD.
Assume a distributed application in which user submits an application for something, say Job/Loan. So the application raises an UserApplied Event.
There are few micro services like credit service, criminal record service.. they consume this UserApplied event do some validation, responds with CriminalCheckPassed, CreditCheckPassed ... etc. Assume there are 5 checks to be done. In future we might also add more checks like this.
The app consume these events and take some decision. That is - only if they are all validated successfully app can approve the user application by changing the status to UserApproved. Any of the validations failed, them it would be UserDeclined. Something like that.
It sounds simple. But I am banging my head how to implement that correctly?
This is my event store
I have a materialized view
If we have to update the materialized view/aggregate whenever we receive an event, app needs 5 different events to take decision. Till then it will be pending. Even when I receive the 5th event, the materialized view does not know how many events it has received before. I will end up querying entire event-store.
Another approach is - adding these columns in the materialized view. So that we know if we have received all these events. It will work. But looks super ugly.
My question is - how to use the aggregation properly in this case?
If I understand correctly, the validation is a part of domain logic (it is something that has to be made sure that it passes). Here, there are some external services like Credit Service and Criminal Record Service.
First, I would model User as an Entity and an Aggregate Root of itself. Then, I will model Job Application as another Entity and another Aggregate Root of itself. Now there are 2 aggregates, with the relationship: User can have many Job Applications.
Now, you need to validate some things before you create a Job Application instance. This validation requires some knowledge from other services. This can be solved by creating a domain service, say JobApplicationCreationService which sole responsibility is to create new instance of Job Application. Then, you would want to inject those external services here. Inside the service, do the validation using the services you injected, then if all validations pass, return a new Job Application instance. This Aggregate instance will have fulfilled your validation rules/domain logic.
Events here is not suitable for validation, rather it is used to synchronize states between Aggregates using eventual consistency. When Events are published and being processed, you want to make sure that the Aggregate that produces the events is already in a consistent state (in this case, the Job Application aggregate).
Here is my personal rule of thumb: Try to create an Aggregate from static factory method to contain the creation logic. If the creation requires something outside of the boundary of the Aggregate itself, refactor it to a Domain Service.
Well, if CriminalCheckPassed are domain events, then they need to somehow mutate the domains state, so you need to store it within your domain (which will be restored when you load your domain entity), say a private readonly List<RequiredCheck> RequiredChecks and check these on recieving of any of the responsible events, then decide.
If it's not a domain event and is not persisted with the aggregate root, then have a process manager (aka Saga) (i.e. UserApprovalProcessmaanger) collect these external events and process/persist them and once all of them are collected fire off an UserApproved / UserDeclined event which is processed by the domain model/aggregate root
Hello I have a question about choreography,
I know it's asynchronous, but in this context:
a requisition in endPoint / addEmployee (where to create an employee the existence in the department is necessary), I would check for an employee and send a message in my department queue to verify the existence and also sign up in the queue to hear the answer, would that be choreography?
Or when confirming the existence of the employee, should I create and send the response already? or can i send the response after consuming the departament queue?
Or in this case, would the orchestration be correct?
If I understand correctly you are receiving a request or a message which contains information to create an employee. One of those field is department name or id. And you would like to validate existence of this department information from department service. Is my understanding correct? If so I would say a lot easier solution would be keeping a basic department data on your employee service. You can get department created, updated events from department service and sync your data instead of asking for each and every employee.
With this solution you wont have a dependency between services. You will just listen the topic or queue to which you wont know where the message comes from which is total opposite of the coupling.
I have 2 option.
1)when addItemTobasket request come. gRPC request to product, pricing, user service and get informations . and save them to cart db.
Or not fetch other service information. Save only references like id. And save basket db. When get basket request call gRPC request aggragate all service datas as viewmodel and return that.
2) create shared redis session server and when addeditem to cart event raise itemAddedToCart includes reference ids. And main services consume that event. Product service get product with id that come with event and write Product info shared redis. pricing service price etc. When getbasket request come data is ready in redis.
For 1) it coupled all servies. it is not good for ddd.
For 2) it is async. When user add item to cart. Waits a responsr success or failed.
If there is better best practice please share with Me.
Honestly I'd say just go with option 1. It's not as complex as there aren't so many interconnected parts. Also depending on the size of your app, that kind of coupling is easy to remove later on when you gain a better understanding of what is going on.
I have a question about the integration events used in a microservice / CQRS architecture.
The payload of the event can only have references to aggregates or can it have more information?
If only reference ids can be sent, the only viable solution is to bring the rest of the information with some type of call but the origin would have to implement an endpoint and the services would end up more coupled.
ex. when a user is created and the event is raised.
UserCreated {
userId
name
lastname
document
...
}
Is this correct?
If only reference ids can be sent,
Why would only that be allowed? I have worked with a system which was using micro-services, CQRS and DDD(similar like yours) and we did not have such restrictions. Like in most cases it is: "What works best for your application/business domain". Do not follow any rule blindly. This is perfectly fine to put other information in the events Payload as well.
the only viable solution is to bring the rest of the information with
some type of call but the origin would have to implement an endpoint
and the services would end up more coupled.
This is fine in some cases as well but this brings you to the situation to have additional call's after the event has been processed. I would not do this unless you have a really heavy model/models and it would affect your performance. For example if you have an event executed and based on userId you would need to load a collection of related objects/models for some reason. I had one similar case where I had to load a collection of other objects based on some action on user like event UserCreated. Of course in this case you don't want to send all that data in one Event payload. Instead you send only the id of the user and later call a Get api from the other service to get and save that data to your micro-service.
UserCreated
{
userId
name
lastname
document
... }
Is this correct?
Yes this is fine :)
What you could do instead:
Depending of your business scenario you could publish the information with multiple events with Stages and in different States.
Lets say from UI you have some Wizard-like screen with multiple steps of creation. You could publish
event: UserCreatedDraft with some initial data from 1st Wizard page
event: UserPersonalDataCreated with only part of the object related to private data
event: UserPaymentDataCreated with only the payment data created
UserCreatedFinal with the last step
Of this is just an example for some specific scenario which depends on your use case and your Business requirements. This is just to give you an Idea what you could do in some cases.
Summary:
As you can see there are multiple ways how you can work with these kind of systems. Keep in mind that following the rules is good but in some cases you need to do what is the best based on your business scenario and what works for some application might not be the best solution for your. Do what is most efficient for your system. Working with micro-services we need to deal with latency and async operations anyways so saving some performance on other parts of the system is always good.
I am designing an Ecommerce using micro services architecture. Suppose that I have two context a product catalog, inventory and pricing.
It's seems clear to me that they have a clear responsibility. But to serve the show case (the product list) I need to make a request for the product catalog, get a list of ID's and then use it to query the Inventory micro services to check inventory status ( in stock or stockout). Besides that I need to make a request to Pricing to get the price of each product.
So basically to serve a fundamental feature makes me execute three requests (like a join) in three micro services. I have been reading about micro services architecture and when you are dealing with many "joins" it's possible that the these contexts should be a single one. But, IMO it seems clear to me that each context has a different set of responsibilities.
The other option is to create a "search" micro service that aggregate all these information (product + pricing + inventory). We can use a domain event to notify "search" microsecond that something has changed. So we can resolve show case with a single request. This look like a CQRS.
The question is...
Is there a correct approach?
Which one is better ? Trade-offs?
you can try to include some information from different domain contexts to other domain context
so you product catalog domain will contain #of items , price from inventory and pricing domains.
This will be a read only (value objects)and should be updated by events from inventory and pricing domains .
in your use case the trusted source of truth will be carried in inventory domain so if any synchronization failure happen still the inventory will reject any order because of availability .
in your case i think its better to create a separate search microservice to aggregate the data from all of them as search is mostly always from multiple domain areas like product , inventory and ....
and you can use events from other microservice (Event Sorucing) to populate the data in search.
It seems that what you need is to show in a view info coming from different microservices (contexts).
You can use ViewModel Composition technic, where an infraestructure component (a request handler) intercepts the http request and allows microservices to participate in the response, looking for a microservice who says "hey, I have that info" (Inventory has the info about stock, Pricing about price, and so on). This infraestructure component compose a dynamic viewmodel on the fly, with the info coming from differect microservices.
I've never implemented it, but look at this video explaining it, from minute 17:35 to 21:00
https://www.youtube.com/watch?v=KkzvQSuYd5I
Hope it helps.
Update on 14-Feb-2019
Probably this will answer your question in more detail https://stackoverflow.com/a/54676222/1235935
I think the right approach here is to use Event Sourcing to pre-aggregate the show case data with product description, inventory and price. A separate microservice is probably not needed. This pre-aggregated data (a.k.a. materialized view) can be stored in the same microservice that handles the user request to display products (probably the order creation service).
The events could be generated by log-based Change Data Capture (CDC) from the DB of the product, inventory and pricing services and writing them to their respective topics in a log structured streaming platform (e.g. Kafka or AWS Kinesis) as mentioned here. This will also ensure "read your own write" guarantees in product, inventory and pricing services