Query Aggregate - Total Order Count/Amount

On our system customers can place orders but only up to a certain total count and total amount per day, lets say for this example a maximum of 10 orders totalling £1000. What I need to determine is the current count and amount of orders placed by a particular customer at any point during the day.

The first two events raised during an order and held against the aggregate contain the data need as follows:

  1. OrderCreateEvent
    Contains the Amount

  2. CustomerAddedToOrderEvent
    Contains a customer Id

I’m attempting without much luck to write a query that can hit the ‘Order’ category returning a total count of orders and total amount of orders for a particular customer on the current day. I believe this should be possible using a single query, I basically want to pass in a customer Id and get a total count & amount returned. Can anyone provide some help?

Sounds like it would be trivial to calculate this in a read model. Any
reason why you're not doing that?

/Rickard

Only reason for not using a standard read model is that the really needs to be up to date and the only place this can be guaranteed is in ES. We cannot have a situation where customers can place more orders than they are permitted.

In my case the read model is updated within 100ms of the event being
stored. If you are really that time sensitive, then perhaps a combo?
Do the query to the read model, but include the version of the
customer, and then compare to version of customer from ES. If they
match, read model result is ok. Otherwise, wait and try again. Should
be safe right?

/Rickard

You options in terms of maintaining integrity is:

  1. Eventual Consistency (you don’t want this).
  2. Make the Customer your Aggregate.
  3. Two phase commit.

For #2, your Customer will become the Aggregrate Root that holds the orders. You can do this even if you have a Customer BC and an Order BC. You will just have a duplicate Customer Aggregate in your Order BC whose sole responsibility will be maintaining this invariant.

For #3, I don’t know how a two phase commit will be done in an ESd model. Have to think about it.

Amjad,

I think your 2nd point (Customer aggregate holding orders) is what we should be doing and probably flags up a potential hole in our system, however due to time constraints on our current iteration this will need to be a future update.

I have however come up with a way round this by including the customer Id within the OrderCreatedEvent and using a projection to create a daily stream for each customer, Customer123__Orders_20170314, when the OrderCreateEvent is generated. I can then just run a query to get all required data from this new customer daily stream.

Thanks for the advice.

Since the numbers are so small put orders for a day in a stream. Replay it.