Event Sourcing Completeness
Event Sourcing Completeness
As of today, we have a fantastic infrastructure to build a complete Event Sourced system with few components.
- Messages
- Pub/Sub
- Routing
- Middlewares
And we have few components related to Event Sourcing following the CQRS docs.
However, I would like to track the completeness of Watermill based on what you are trying to accomplish.
Completeness could mean either it supports the feature with some level of abstraction and/or has some documentation about it helping to implement by themselves.
These are some notes of what I think the completeness list would be, but feel free to send feedback about it, I am more interested in starting a discussion and have a thread for it.
Commands
- [ ] Command Bus: Message bus for commands.
- [ ] Command: data structure representing a command.
- [ ] Command Handler: handles the incoming commands.
- [ ] Router: routes the incoming command to its command handler.
- [ ] Validations: validates the command before dispatching the command.
Events
- [ ] Event Bus: Message bus for events.
- [ ] Event: data structure representing an event.
- [ ] Event Handler: handles the incoming events.
- [ ] Event Store: stores events.
- [ ] Snapshot: a snapshot of the event stream.
Extra
Also, add some extra abstractions or documentation, helping people to deal with common use cases.
- [ ] Idempotence: refers to the ability of a system to produce the same outcome even if an event or message is received more than once.
- [ ] Aggregate Id: This field is used to associate the particular event to a specific Aggregate Root.
- [ ] Causation ID: the ID of the command causing an event, or the event causing a command dispatch.
- [ ] Correlation ID: the ID used to correlate related commands/events.
Aggregates
- [ ] Aggregates: is comprised of its state (Aggregate Root), public command functions (Command Handlers), and state mutators (Event Handlers).
- [ ] Aggregate Root: data structure representing an aggregate.
Process Manager
- [ ] Process Manager: is responsible for coordinating one or more workflows. It handles events and dispatches commands in response.
Saga
Saga: distribution of multiple workflows across multiple systems, each providing a path (fork) of compensating actions if any of the steps in the workflow fails.
Read Model Projection
- [ ] Read Model Projection: read model can be built using an event handler and whichever storage provider you prefer.
Thoughts?
Commands
- [x] Command Bus: Message bus for commands.
- [x] Command: data structure representing a command.
- [x] Command Handler: handles the incoming commands.
- [x] Router: routes the incoming command to its command handler.
- [ ] Validations: validates the command before dispatching the command. ~it depends what validation means ;) but at this moment if command can be marshaled - it will be published
Events
- [x] Event Bus: Message bus for events.
- [x] Event: data structure representing an event.
- [x] Event Handler: handles the incoming events.
- [ ] Event Store : stores events. ~The closest implementation is SQL Publisher, but it doesn't have all logic connected to aggregates, versioning, etc.
- [ ] Snapshot: a snapshot of the event stream.
Extra
Also, add some extra abstractions or documentation, helping people to deal with common use cases.
- [ ] Idempotence: refers to the ability of a system to produce the same outcome even if an event or message is received more than once. ~it may be tricky to provide universal solution for that, I was thinking about the middleware to support it but in practice, we assume that it's the responsibility of called functions to be idempotent
- [ ] Aggregate Id: This field is used to associate the particular event to a specific Aggregate Root. ~As mentioned with Event Store - currently it's not supported, I'm thinking how to make it compatible with Pub/Sub to use the current abstraction
- [ ] Causation ID: the ID of the command causing an event, or the event causing a command dispatch. ~Sounds like a good idea :) I will think about it
- [x] Correlation ID: the ID used to correlate related commands/events. ~for simple cases you have the middleware to support it, but it also depends so I can imagine that you may be interested with developing your own :)
Aggregates
- [ ] Aggregates: is comprised of its state (Aggregate Root), public command functions (Command Handlers), and state mutators (Event Handlers).
- [ ] Aggregate Root: data structure representing an aggregate.
Process Manager
- [x] ? Process Manager: is responsible for coordinating one or more workflows. It handles events and dispatches commands in response. ~here is no mechanism to do it out of the box, but it can be implemented pretty easily with CQRS Event Handler (unless it's not event-sourced ;) )
Saga
- [x] ? Saga: distribution of multiple workflows across multiple systems, each providing a path (fork) of compensating actions if any of the steps in the workflow fails. ~same case, like with Process Managers
Read Model Projection
- [x] ? Read Model Projection: read model can be built using an event handler and whichever storage provider you prefer. ~same case, like with Process Managers
@yordis, @roblaszczak
I played around with CQRS/ES in go some time ago. Here's an example of a very naive implementation: https://github.com/screwyprof/cqrs/blob/master/examples/bank/bank_test.go
I'm planning to try to use sql-pubsub to run this example. The reason I'm mentioning it is that you may find useful the way I implemented the Aggregate https://github.com/screwyprof/cqrs/tree/master/pkg/cqrs/aggregate. In this case your Domain entities won't depend on infrastructure. Here's an example https://github.com/screwyprof/cqrs/blob/master/examples/bank/pkg/domain/account/account.go
Hey @yordis @screwyprof @roblaszczak let's talk more about it.
I'm using the watermill in some personal projects and It's so powerful and simple. But as @yordis mentioned there is some things that could have some abstraction and/or has some documentation. For me Aggregates is the difficult thing to newbies in ES to understand and use, so if some support is provided it will be nice.
Hey @mirusky . If we were to discuss the CQRS/EventSourcing/DDD and Aggregates in particular it would be a very long discussion. A lot of books have writen on the subject. I'd recomment to start with the following:
- https://www.amazon.co.uk/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=asc_df_0321125215/?tag=googshopuk-21&linkCode=df0&hvadid=310831942794&hvpos=&hvnetw=g&hvrand=10349513597049134207&hvpone=&hvptwo=&hvqmt=&hvdev=m&hvdvcmdl=&hvlocint=&hvlocphy=9044962&hvtargid=pla-449269547899&psc=1&th=1&psc=1
- http://cqrs.nu/
In a nutshell:
- https://www.infoq.com/minibooks/domain-driven-design-quickly/
- https://github.com/gregoryyoung/m-r/tree/master/SimpleCQRS
Actually I'm more interested in some kind of implementation, I know that an Aggregate should put "component" logic together and be responsable for track the state of the aggregate.
For example
-
InventoryItem from m-r.
-
Order from https://github.com/fChristenson/A-case-for-event-sourcing
-
Order from https://github.com/dotnet-architecture/eShopOnContainers
In my conception, aggregate receives commands / execute business associated actions ( eg. methods item.ChangeName("newName") ) and then creates events. So thinking about the watermill ecosystem how it could be implemented ? Since there no way to handle multiple events/commands at once.