watermill icon indicating copy to clipboard operation
watermill copied to clipboard

Event Sourcing Completeness

Open yordis opened this issue 6 years ago • 5 comments

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?

yordis avatar Oct 14 '19 12:10 yordis

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

roblaszczak avatar Oct 22 '19 19:10 roblaszczak

@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

screwyprof avatar Mar 02 '21 02:03 screwyprof

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.

mirusky avatar Aug 30 '21 05:08 mirusky

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

screwyprof avatar Aug 30 '21 14:08 screwyprof

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.

mirusky avatar Sep 01 '21 23:09 mirusky