简体   繁体   中英

EventSourcing and DDD Entity events

I have a DDD project using EventSourcing. And currently there are many aggregate roots many of which have collections of entities. Even more - some entities have collections of other entities.

Problem: Reading EventSourcing event log for audit purposes.

Question: What is the best way to save events in EventStore when an entity is Updated/Created/Removed having all these things in mind: they have to be easily readable, versions, may be not for this case but usually granular events are preferable, probably domain-events are going to be used for cross domain communication.

  1. Should I save in the root stream the whole root with all collections of entities inside as a RootChangedEvent ?

  2. Should I save only the entity which was Updated/Created/Removed in the root stream as a EntityChangedEvent/EntityCreatedEvent/EntityRemovedEvent

  3. Should I save in the root stream Two events - one for the root - RootChangedEvent with only the version property + second for the entity which will have only a single property if such changed in EntityChangedEvent or whole entity if EntityCreatedEvent or only id if EntityRemovedEvent (How to handle if entity of entity created/updated/removed?)

Here is an example in my project:

The root - Pipeline.

public class Pipeline : AggregateRoot<IPipelineState>

It has collection of entities - public IList<Status> Statuses .

And each Status has collection of entities - public IList<Logic> Logics .

All collections could store a lot of entities. And right now I raise events like PipelineCreatedEvent, PipelineChangedEvent (not only when Pipeline changed but even when adding, updating, removing Status or Logic) and PipelineRemovedEvent.

There should be a single stream of events for any given aggregate, to avoid race conditions. Aggregate is a transaction boundary.

In your case, try to formulate what happened in your system not in terms of Entities, but in business words:

  1. OrderCreated (orderId=123)
  2. OrderItemAdded (orderId=123, 'product1')
  3. OrderItemAdded (orderId=123, 'product2')
  4. OrderItemRemoved (orderId=123, 'product1')
  5. OrderPaid (orderId=123)
  6. OrderArchived (orderId=123)

These events happened with what? With Order so order is your aggregate root, and 123 - its aggregateId. You may not even need OrderItems there, unless this is required by command handler (say, you don't want to emit OrderItemRemoved event for already removed item).

You will have a single event stream for aggregateRoot 123, and nobody can, say, add and OrderItem while you are processing PayOrder command.

It is important to understand that the more business specific your events, the more flexibility you'll have later with domain aggregates and read models. Remember, your events are immutable and will be there forever!

OrderEntityChangedEvent (new Status = Paid) implies particular structure of your entities OrderPaid events assume nothing except there is an Order Aggregate root somewhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM