Example event sourcing and CQRS implementation in golang
Project is a re-implementation of [https://github.com/pinballjs/event-sourcing-cqrs] in GO. Initial inspiration originates from Chris Richardson's presentation
git clone https://github.com/botchniaque/eventsourcing-cqrs-go.git
cd eventsourcing-cqrs-go/
export GOPATH=`pwd`
go get -t -v example eventsourcing
go build example
./example
to run tests
go test -v eventsourcing
Example implements 2 aggregates - Account and Money Transfer
implementation includes number of components:
Event Store
- persists events, and allows searching by aggregate ID.Event Handler
- gets notified about persisted events, and produces commands as a result of some events (eg.DebitAccountCommandBecauseOfMoneyTransfer
when receivesMoneyTransferCreatedEvent
)Command Handler
- each aggregate has own handler, which produce state changing events, which then are persisted in theEvent Store
- Customer facing
Services
- expose usable functions to clients and produce commands as a product of interaction
Sketched diagram:
+---------------+ +--------------+
| Event Handler | | Event Store |
| | | * Update |
| +<---Persisted Events----+ * Find |
| | Channel | |
+-------+-------+ +------+-------+
| ^
commands events
| |
| +---------+---------+
+---------> | Command Handler |
\ | - Account |
+-----Command---> | - Money Transfer |
/ Channel(s) | |
+------> +-------------------+
|
comamnds
|
+----------+--------+
| Service |
| - Account |
| * Open |
| * Credit |
| * Debit +<---Customer requests---+
| - Money Transfer |
| * Create new |
| |
+-------------------+
After persisting, Event Store
should publish events to a proper Message Bus
where components
can subscribe to those events. In the example, for simplification,
the Persisted Events Channel
works as a single-subscriber Message Bus
- since channels are
first-class citizens in GO, this simplified a lot, but it's not enough for real-life implementations.
To implement a simple bus allowing multiple subscribes, a 'linked channel' idea could be implemented as described here
Example uses simple map/slice implementation of Event store
. For real-life implementations events would
need to be serialized (probably to JSON) for persistence. For simplification that part was omitted.