https://github.com/nkonev/go-cqrs-example
https://github.com/nkonev/go-cqrs-example
cqrs cqrs-architectural-pattern cqrs-pattern docker docker-compose go golang kafka postgres postgresql watermill
Last synced: 6 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/nkonev/go-cqrs-example
- Owner: nkonev
- Created: 2025-04-06T03:24:18.000Z (6 months ago)
- Default Branch: master
- Last Pushed: 2025-04-13T17:18:21.000Z (6 months ago)
- Last Synced: 2025-04-13T17:25:39.172Z (6 months ago)
- Topics: cqrs, cqrs-architectural-pattern, cqrs-pattern, docker, docker-compose, go, golang, kafka, postgres, postgresql, watermill
- Language: Go
- Homepage:
- Size: 75.2 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# Example Golang CQRS application
This application is using [Watermill CQRS](http://watermill.io/docs/cqrs) component.
It's an improved [6-cqrs-ordered-events](https://github.com/ThreeDotsLabs/watermill/tree/v1.4.6/_examples/basic/6-cqrs-ordered-events) example.
Events are stored in Kafka, projections are stored in PostgreSQL.
We can reset our projections and then restore their state from Kafka by resetting offsets.
See [It's Okay To Store Data In Kafka](https://www.confluent.io/blog/okay-store-data-apache-kafka/).
# Start
```bash
docker compose up -d
go run .
```# Play with
```bash
# create a subscriber
curl -i -X POST --url 'http://localhost:8080/subscribe'# see subscribers
curl -Ss -X GET --url 'http://localhost:8080/subscribers' | jq# update the subscriber
curl -i -X PUT --url 'http://localhost:8080/update/216681f5-e73e-4461-926e-019445b9913b'# unsubscribe
curl -i -X POST --url 'http://localhost:8080/unsubscribe/216681f5-e73e-4461-926e-019445b9913b'# see activities
curl -Ss -X GET --url 'http://localhost:8080/activities' | jq# clear projections
docker compose exec -it postgresql psql -U postgres -c 'truncate subscriber; truncate activity_timeline;'# now there are zeroes
curl -Ss -X GET --url 'http://localhost:8080/subscribers' | jq
curl -Ss -X GET --url 'http://localhost:8080/activities' | jq# stop app
# reset offsets for consumer groups
docker compose exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server kafka:29092 --group SubscriberProjection --reset-offsets --to-earliest --execute --topic events
docker compose exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server kafka:29092 --group ActivityTimelineProjection --reset-offsets --to-earliest --execute --topic events# start app again
go run .
# and it will restore tables from the zeroth offset, see
curl -Ss -X GET --url 'http://localhost:8080/subscribers' | jq
curl -Ss -X GET --url 'http://localhost:8080/activities' | jq
```# Tracing
See `Trace-Id` header and put its value into [Jaeger UI](http://localhost:16686)# Various commands
```bash
# see logs
docker compose logs -f kafka
docker compose logs -f postgresql# see projections
docker compose exec -it postgresql psql -U postgres
select * from subscriber order by created_timestamp;
select * from activity_timeline order by created_timestamp;docker compose exec -it kafka bash
docker compose exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server kafka:29092 --list
docker compose exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server kafka:29092 --describe --group SubscriberProjection --offsets
docker compose exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server kafka:29092 --describe --group ActivityTimelineProjection --offsets# see kafka topic
docker compose exec -it kafka /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server kafka:29092 --topic events --from-beginning --property print.key=true --property print.headers=true
```