Order Service is a simple Web API.
- Clean Architecture
- Experiments with DDD
- CQRS (All but one method use half of the CQRS;
GetAllOrdersByUserID
uses the cache) - Outbox Pattern
- Saga Pattern(Choreography-based)
- Mediator with Query and Command Bus(
MediatR
inspired)
To use Saga pattern need external CustomerService
or you can simulate events with RabbitMQ admin panel
curl -X "GET" "http://localhost:8000/healthcheck/"
{"status": "OK"}
To create order need some product, address and client.
curl -X "POST" \
"http://localhost/api/v1/products/" \
-d '{
"productID": "ec14f9be-44e3-4ec0-97d3-47fdac6c55c9",
"price": 100,
"discount": 10,
"Description": "string",
"Name": "string"
}`
Status 204 No Content
curl -X "POST" \
"http://localhost/api/v1/address/" \
-d '{
"addressID": "7b2b575e-65e7-427c-bb1b-1fe609fc1f6b",
"buildingNumber": 44,
"streetName": "string",
"city": "string",
"country": "string"
}`
Status 204 No Content
curl -X "POST" \
"http://localhost/api/v1/users/" \
-d '{
"userID": "4b2b575e-65e7-427c-bb1b-1fe609fc1f6b",
"username": "string",
"addressID": "7b2b575e-65e7-427c-bb1b-1fe609fc1f6b"
}`
Status 204 No Content
curl -X "POST" \
"http://localhost/api/v1/orders/" \
-d '{
"orderID": "1b2b434e-44e8-424c-bb1b-1fe609fc1f7d",
"paymentMethod": "string",
"productsIds": ["ec14f9be-44e3-4ec0-97d3-47fdac6c55c9"],
"userID": "4b2b575e-65e7-427c-bb1b-1fe609fc1f6b",
"deliveryAddress": "7b2b575e-65e7-427c-bb1b-1fe609fc1f6b"
}`
After creating an order, need to imitate a response from a third-party service
- CustomerSaga Queue Payload
{
"orderID": "1b2b434e-44e8-424c-bb1b-1fe609fc1f7d",
"orderType": "Approved"
}
After publish payload can get orders:
- From DB
curl -X "GET" "http://localhost:8000/api/v1/orders?limit=10&order=asc"
{
"orders": [
{
"orderStatus": "New",
"paymentMethod": "Online",
"client": {
"ClientID": "4b2b575e-65e7-427c-bb1b-1fe609fc1f6b",
"ClientName": "test"
},
"address": "Russia, Moscow, Pushkina, 44",
"OrderID": "1b2b434e-44e8-424c-bb1b-1fe609fc1f7d",
"serialNumber": 1,
"products": [
{
"productID": "ec14f9be-44e3-4ec0-97d3-47fdac6c55c9",
"name": "he3444443h1",
"actualPrice": 90
}
],
"createdAt": "2023-07-23T00:27:52.641012+03:00",
"totalPrice": 90
}
],
"count": 1,
"limit": 10,
"order": "asc"
}
- From Redis Cache
curl -X "GET" "http://localhost:8000/api/v1/orders/user/4b2b575e-65e7-427c-bb1b-1fe609fc1f6b?limit=10&order=desc"
{
"orders": [
{
"orderStatus": "New",
"paymentMethod": "Online",
"client": {
"ClientID": "4b2b575e-65e7-427c-bb1b-1fe609fc1f6b",
"ClientName": "test"
},
"address": "Russia, Moscow, Pushkina, 44",
"OrderID": "1b2b434e-44e8-424c-bb1b-1fe609fc1f7d",
"serialNumber": 1,
"products": [
{
"productID": "ec14f9be-44e3-4ec0-97d3-47fdac6c55c9",
"name": "he3444443h1",
"actualPrice": 90
}
],
"createdAt": "2023-07-23T00:32:00.414866435+03:00",
"totalPrice": 90
}
],
"count": 1,
"limit": 10,
"order": "desc"
}
- Postgres — Database
- RabbitMQ — The queue used to publish and handle events
- Redis — For Query cache
- Docker — For deployment
- Grafana — Web view for logs and prometheus info
- Loki — A platform to store and query logs
- Vector.dev — A tool to collect logs and send them to Loki
- Prometheus — A tool to alerting series info
- Gin - Web framework
- Gorm - ORM for working with database
- go-redis - Cache database for query request
- cron - To implement relay from Outbox pattern
- fx - A dependency injection tool for easy initialization and delivery of dependencies
- zap - For better logging config
- amqp091-go - For working with RabbitMQ
The first thing to do is to clone the repository:
git clone https://github.com/MikhailGulkin/CleanGolangOrderApp
cd CleanGolangOrderApp
After that create .env
and configs/app/prod.toml
. Examples for use lie next to these files.
Run following command
make up-prod
- Refactoring auto-tests
- Configure CI
- Create simple
CustomerService