Really liked the last alternative. Instead of trying to come up with a complicated distributed transaction schema you went to the source of the problem and came up with a more elegant and reliable solution 👍
@CodeOpinion Жыл бұрын
Glad you got to the end of the video to see it!
@lextr3110 Жыл бұрын
what is complicated about distributed transaction? its a lot simple than his event architecture
@CodeOpinion Жыл бұрын
@@lextr3110 I'd love to hear how it's simpler. Service-to-service 2pc would require everything to be blocking. Unless you had some type of sync blocking orchestration, you'd have no idea the network hops to services you'd be making. In other words you're contending with high latency... which again is blocking.
@lextr3110 Жыл бұрын
@@CodeOpinion you can make async calls that will not block, even from service to service, and it will clearly be faster than events with all their complexity. I'm not ditching out events for some subscribing microservices that does not care about loosing events/data.. but you need to make sure all the data in all dependent microservice database is perfectly saved before returning to the user and for this, async distributed transaction is better than risking weird data drift between microservices databases.. not sure why you don't point out to peoples that there is easier and safer distributed async crud pattern that should be use most of the time for any important crud operations. You can also do parallel service to service call if needed where possible for faster execution.. To return a "stored" event to the client/user when the full data is yet to be stored totally in all dependent microservice database is just playing with the devil..
@CodeOpinion Жыл бұрын
@@lextr3110 In-process threading is still blocking. You ultimately need it to return to confirm it completed. It's not durable. If you make a async call eventually you're going to await for it to make sure it completed. If your process crashes at any point during that, then what? Also, to the point it's faster is not true. The more threads in a process your producing the more memory consumed. You will hit a point at which you've consumed all resources and it will not be faster. You have an upper bound of throughput that is dependent on other services latency. I'd love to point out if there were easier and safer methods, but unless your using a DTC, you're not going to be getting a distributed transaction. Can you point me to what you're referring to as a "easier and safer distributed async crud"?
@dropbeardan9604 Жыл бұрын
I have to say, one of the more concise and clear cut explanations for this topic by far. Looking forward to your micro-ui video!
@marna_li Жыл бұрын
I have followed the thread. Yes, the last solution is the simplest and cleanest: Keep the concept of an Order in the Payment service, and listen to events from Order service to update the data kept in Payments service. I'm familiar with approach, but I do admit that it would take me some time to realize that this is an acceptable solution. Storing information related to Order in Payment service is perhaps not how I would intuitively do it. This is the solution to the author's (of the question) worries about decoupling and preferring to do doing synchronous calls from Order service to the Payment service.
@CodeOpinion Жыл бұрын
Ya, I think most wouldn't find it intuitive for the reasons I mentioned: Focus on entity services and ultimately thinking about queries.
@marna_li Жыл бұрын
@@CodeOpinion Programmers thinks in terms of sequential operations, even between services. It takes some time to get used to events and to learn what you can do with them. Syncing data with events is a useful technique. And it simplifies the way you reason about a system. In my experience, a lot of software developers would be uncomfortable with what you are suggesting. Even more so if they are committed to the old ways. So we need more pragmatism in the field.
@CodeOpinion Жыл бұрын
Ya, related to messaging, I've noticed a trend of people feeling like it's magic and "what if the message is lost!?!". As in that it's not going to be reliable.
@BosonCollider Жыл бұрын
Another option when you are small: use a decoupled monolith with shared databases in different schemas. This lets you use database transactions.
@arielmoraes9427 Жыл бұрын
We have a domain with similar flows but different boundary names, the difference is that the "Payment" context can accept multiple types of inputs not only "Orders". In that case our solution was to create a service for each entity that should have a payment and each service creates payments synchronously, and the Payment service itself doesn't care about the origin of the payment.
@scottamolinari Жыл бұрын
I'd just like to point out, if there is a policy of overdrafting orders, then that should be within the payment/ subscription service. The order service should be dumb to the policy. In other words, the order system should keep on plugging out orders, until it is told to stop. The payment/ subscription service is the one handling the "kill order" or "continue order" commands. So, if the order service sent out two orders, yet the customer hadn't bumped up the payment, the balance would become negative. This state would also be used to consider killing the order process too. The way the process was presented, the payment/ subscription process was oblivious to the outgoing orders, until the customer actually paid again. No way that is going to be working well.
@rahulsen002 Жыл бұрын
I was asked the same question in a different form in an interview.. now I know why I was rejected 😅😅
@CodeOpinion Жыл бұрын
What was your answer/response?
@khaledelnagar4135 Жыл бұрын
When designing your system, especially the data boundaries, it would be extremely counter-intuitive to expect that a payment system would have to know about an order status, and that the order service itself does not have it (unless with a carry state event). I mean I realize that setting data boundaries is not simple as it seems.
@sirg7573 Жыл бұрын
Once again, great video! 6:12 mins into the video you have mentioned that you will put a link in the description to the request-reply pattern. Looks like the link is missing. Could you please add?
@CodeOpinion Жыл бұрын
Oops. Here it is: kzbin.info/www/bejne/bIamZ5WqfJiqjKs
@ugochukwuumerie6378 Жыл бұрын
Cool love the last concept, instead of some type of sagas for distributed transaction. Have you done the 'UI and view compositions' video yet?
@CodeOpinion Жыл бұрын
Not yet! I need to get to this! I will, I promise!
@budi0580 Жыл бұрын
Does the order service is a background consumer ? In visual studio what project that we can use ?
@phillipsma Жыл бұрын
Nice video, especially the last part about presentation often dictating what happens at the backend. Looking forward to the follow up viewmodel composition series. As an NSB champ I'll assume you've heard of Mauro Servienti? If so, are you familiar with his blogs on viewmodel composition too?
@CodeOpinion Жыл бұрын
Yup! I might reference his example project as one solution.
@phillipsma Жыл бұрын
@@CodeOpinion Awesome. You do great content, good use of the diagrams, and just the right length to get the point across too. Keep it up please.
@lextr3110 Жыл бұрын
You did not awnser the question?? why distributed async crud transaction is wrong?
@JamesGardner159 Жыл бұрын
Great Video!
@CodeOpinion Жыл бұрын
Glad you enjoyed it
@ivandrofly Жыл бұрын
5:15 Dead letter queue
@arielmoraes9427 Жыл бұрын
About the view composition, may you show how to tackle data that should be composed and displayed on rows format (table)? My approach is to aggregate the data by listening to events and building a read model in a front end component like a BFF.
@CodeOpinion Жыл бұрын
Yup, I'll talk about that.
@benjaminbrepols9827 Жыл бұрын
In your example, I still have one remark/question: how do you find which order needs to be updated within the payment domain? From what I understood, the link exists between the subscription and the customer then the customer is linked with the orders within the Order domain. You can see it in your view when you move a part of the Order, there's no information to know that. I also have a hard time for the correlation ID used to communicate here between the different domain: sometimes you use the CustomerId (I suppose), sometimes it's the OrderId. I know that we can use the SagaFinder to solve the issue but it seems like we are missing something, what do you think?
@CodeOpinion Жыл бұрын
The OrderID would be apart of pretty every message. In my last example, when an OrderPlaced event is published, that event would contain the OrderID. The payment service would consume it and add to its DB a record for that OrderID.
@brtk7 Жыл бұрын
When there will be part about obtaining data for view models? Thanks for yours channel!
@CodeOpinion Жыл бұрын
Coming soon!
@brandonpearman9218 Жыл бұрын
Restructure your boundaries. There is a weird obsession amongst architects to cut data up as small as possible regardless of the use case.
@CodeOpinion Жыл бұрын
IMO boundaries are one of the most important things to do, the hardest to get right. In the vast majority of my video's I'm giving simple examples of a "small" data structure. Reality is, even in this video I'd assuming in the real world, the payment service isn't 3 tables/documents with a few properties. I'm using it as high level example. The point isn't to cut data up "as small as possible", it would be to cut it up into boundaries where the data actually relates. My HR department cares about very different data than the IT department.
@brandonpearman9218 Жыл бұрын
@@CodeOpinion if 2 departments care about different data, it would be great to split them up but lets assume we have a case that it is creating a technical nightmare what are the issues/cons with joining that data into one service and db? The same service can have the exact same end points and exposed data as if they were separate.
@CodeOpinion Жыл бұрын
@@brandonpearman9218 Ya for sure it's feasible that you compose the data into one service, but that's usually for query purposes. Data is still owned by it's respective boundary.
@LawZist Жыл бұрын
Regarding the boundaries section - Isn’t it a microservices anti pattern to query the same table (orders) from multiple services?
@guazpl Жыл бұрын
In this solution there would be two Order tables - one in each boundary. They would have different sets of columns. Services would read and write only Orders table they own.
@LawZist Жыл бұрын
@@guazpl So does it mean that for every record in one service db table there is a matching record on the other service db table?
@guazpl Жыл бұрын
@@LawZist That's true - records in both tables would match by orderId. They would be synchronized with events sent from Orders to Payments. In example shown in video the tables are basically the same and it may feel like unnecessary duplication. However in real domain table in Orders service would probably have more attributes related to order than table in Payments which is concerned only about amount and status. This example shows how making entity based services - "everything related to orders" or "everything related to payments" - may not be a good idea.
@z0nx Жыл бұрын
12:03 Anybody got links to these vids? Finding those via the youtube UI is actually kind of hard :>
@CodeOpinion Жыл бұрын
Here you go: kzbin.info/www/bejne/f33Fm36IZquLpcU
@dayanshuwang2508 Жыл бұрын
ok, to summarise, if you are good sale guy, you can do engineering well, by manipulate the words to customers, its really how we present data meanings to customer, haha
@MintoIssac Жыл бұрын
Just a feedback on all your videos, This may make me look stupid, Your videos are incredible, And I genuinely hope that you get more viewers going forward. The thing is, For a lot of us English is our second or third language and most of us never had a proper CS education, I find it difficult to understand some of the fancy words used in your videos, I am ashamed to say despite being almost 7 years in the industry I don't understand what is meant by the word 'idempotent' but I probably know what it represents. Yes, I understand that as a viewer and a student I need to put some more effort and take the responsibility to learn more of these words if I want to move forward in my career. But this could be one of those areas of improvement where the global audience could be benefited from your videos.
@CodeOpinion Жыл бұрын
Thank you for the comment! It's much appreciated. Agree that sometimes I reference and use words that I assume the viewer is aware of. I should at least give a bit of definition to these words when I use them and not assume. Again, thanks for the feedback.
@ryanelfman3520 Жыл бұрын
I don’t understand the benefits of doing this. This feels like a distributed monolith
@CodeOpinion Жыл бұрын
Making an RPC call but requiring consistency between boundaries is a distributed monolith. Both services need to be online and available for the process to work correctly. Otherwise your left in an inconsistent state.
@ryanelfman3520 Жыл бұрын
@@CodeOpinion I get that but even the scenario where you have an order object in the payment service. Maybe it’s just too simple of an example but why not just have 1 service? Do you need separation release cycles, and all the other text book so called micro services benefits? Micro services like this to me are too small. Micro services should be seen as separate businesses. Imagine an external client having to call two services to get information about an order. They wouldn’t be too happy I don’t think. Then the solution is to have some sort of api gateway in front of that, and complexity grows. All that being said great articulated video tho
@CodeOpinion Жыл бұрын
Should it be two services? Who knows really, I didn't know the full context from the person asking the question. I could see it being two, given how large they likely are based on my own experience in various domain. But absolutely having one boundaries instead if two could of been a solution. Assuming it's not and you can't/shouldn't, the last example is often the solution I these types of situations where you want a distributed transaction.