 |
BOOK: Patterns, Principles and Practices of Domain-Driven Design
 | This is the forum to discuss the Wrox book Patterns, Principles and Practices of Domain-Driven Design by Scott Millett; ISBN: 978-1-118-71470-6 |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the BOOK: Patterns, Principles and Practices of Domain-Driven Design section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

June 4th, 2015, 07:23 AM
|
|
Authorized User
|
|
Join Date: May 2015
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Event Store as a Message Bus
We have briefly touched on this Event Store (ES) scenario before. I'm trying to understand using Event Store only, and NO Message Queue or Bus.
The scenario is, an OrderManager BC polls the ES and receives an event called OrderPlaced and delegate the work to an Order Aggregate. It raises another event called CheckCreditCard which is handled by CreditCardProcessor BC. The OrderManager in it's polling process gets CreditCardVerified event from the ES. It raises another event called OrderConfirmed. The Shipping BC in a polling process gets the OrderPlaced event and ships the product to the customer. Since all these different BCs have to communicate to each other, all three have to do polling and hand over the events to the appropriate aggregates.
Let us assume the system that hosts the OrderManager crashes after the CheckCreditCard event is published. The other two BCs are alive. And little later the OrderManager comes up.
1. As part of the replay logic to generate the latest state, the Order aggregate replays all the events. In that replay process, CheckCreditCard will be sent again which will be persisted in the ES again. This has been already sent previously before the crash. How to avoid this situation and don't re-process events that have been sent to external BCs?
2. Since there is already CreditCardVerified event in the ES so the Order can process it. Here the situation that can happen is the Order is replaying events to restore it's state but it happened only after the Order changed it's state to OrderPlaced. How to make sure that the Order aggregate events are handled after the events are replayed.
3. This question depends on the answer to the question 1. How to make sure the OrderPlaced event is published to the ES so the Shipping BC can process it and ship the product.
In a nutshell, the question is on using ES to store events, recover state, continue where left off before the crash.
I appreciate your response.
Last edited by varghesep; June 4th, 2015 at 07:32 AM..
|
|

June 6th, 2015, 03:19 PM
|
|
Wrox Author
|
|
Join Date: May 2015
Posts: 59
Thanks: 1
Thanked 5 Times in 5 Posts
|
|
Hi,
Just to clarify, technically you would be using Event Store as a message queue as you alluded to. A message bus is more about delivering messages, whereas here we would just be using event store to store events - aka a queue.
You can use Event Store as a queue, though, definitely.
This relates directly to the problem scenario you mention. Essentially, the CheckCreditCard event will not be sent again, because events are not sent when state is replayed. Events are polled. So the component/service that processes the CheckCreditCard stores the ID of the events it has processed. Therefore, it won't look at the events with IDs it has already processed.
Does that help? I think if you view the Event Store as a queue (just for storing events) and not a bus, that might help you understand my intention. But if not just let me know and I'll try again.
|
|

June 7th, 2015, 07:57 AM
|
|
Authorized User
|
|
Join Date: May 2015
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Reprocessing
I understand from your reply that whenever a component recovers from a crash, only the events that generate it's state need to be replayed. In this case, although the event CheckCreditCard is stored in the ES, should not act on that event. Do you suggest some type of indicator in the event saying ShouldNotReProcess and setting true for that variable for the CheckCreditCard event?
In the Mean time, the component that process the CheckCreditCard should check that it has already processed the event? Don't you think it is expensive to query the persistent ES every time it receives the event to make sure it has not processed before? In the case of CheckCreditCard, keeping millions of events it has processed in the memory is not a good idea.
I would appreciate if you can touch on the third question also. The question is how to coordinate the replay events to restore the state Vs processing of the event it receives? If they are out of order, the aggregate wont show the latest state correctly. It can send an OrderPlaced event, thus the state of the aggregate changed to OrderPlaced. But the replaying of the events to restore the state overwrote the state to not placed.
Last edited by varghesep; June 7th, 2015 at 08:05 AM..
|
|

June 7th, 2015, 08:53 AM
|
|
Wrox Author
|
|
Join Date: May 2015
Posts: 59
Thanks: 1
Thanked 5 Times in 5 Posts
|
|
It's worth thinking about CheckCreditCard again. That's really a command, not an event so you wouldn't store it in an event stream.
You might have:
- an order placed event
- a component subscribes to order placed and checks the credit card
- after checking the credit card it stores a CreditCardChecked event in the relevant stream
The other important detail to be aware of is that when you replay an event stream to calculate state, you don't invoke your domain model to re-process all of the events. You simply have a projection that condenses the values of each event into a single snapshot.
|
|

June 7th, 2015, 07:25 PM
|
|
Authorized User
|
|
Join Date: May 2015
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Commands
Thanks for clarifying that the commands should not be logged.
|
|
 |
|