-
-
Notifications
You must be signed in to change notification settings - Fork 8
docs: improve and restructure README for better clarity #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,105 +1,155 @@ | ||||||||||||||||||||||||||||||||||
| # E-commerce Microservices (Python, Flask, MySQL, SQS) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Services | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - order_service (A): REST + MySQL + publishes SQS order events | ||||||||||||||||||||||||||||||||||
| - product_service (B): REST + MySQL (catalog) | ||||||||||||||||||||||||||||||||||
| - user_service (C): REST + MySQL (users) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Infra | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - 3x MySQL containers | ||||||||||||||||||||||||||||||||||
| - LocalStack (SQS) | ||||||||||||||||||||||||||||||||||
| - Docker Compose to orchestrate | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Quick start | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - docker compose up -d --build | ||||||||||||||||||||||||||||||||||
| - docker compose logs -f order_service product_service user_service | ||||||||||||||||||||||||||||||||||
| - docker compose down -v | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| APIs | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - OpenAPI specs in each service under openapi.yaml | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # E-commerce Microservices Architecture | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| This repo contains three Python (Flask) microservices orchestrated with Docker Compose, each with its own MySQL database, plus LocalStack SQS for messaging. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Architecture (single diagram) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```mermaid | ||||||||||||||||||||||||||||||||||
| flowchart LR | ||||||||||||||||||||||||||||||||||
| client([Client / Postman]) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| subgraph "Order Service :8080" | ||||||||||||||||||||||||||||||||||
| order_svc([Order Service]) | ||||||||||||||||||||||||||||||||||
| o1["POST /api/v1/orders"] | ||||||||||||||||||||||||||||||||||
| o2["GET /api/v1/orders"] | ||||||||||||||||||||||||||||||||||
| o3["GET /api/v1/orders/{id}"] | ||||||||||||||||||||||||||||||||||
| o4["GET /api/v1/orders/{id}/details"] | ||||||||||||||||||||||||||||||||||
| o5["POST /api/v1/orders/{id}/pay"] | ||||||||||||||||||||||||||||||||||
| o6["POST /api/v1/orders/{id}/cancel"] | ||||||||||||||||||||||||||||||||||
| o7["GET /health"] | ||||||||||||||||||||||||||||||||||
| order_svc --- o1 | ||||||||||||||||||||||||||||||||||
| order_svc --- o2 | ||||||||||||||||||||||||||||||||||
| order_svc --- o3 | ||||||||||||||||||||||||||||||||||
| order_svc --- o4 | ||||||||||||||||||||||||||||||||||
| order_svc --- o5 | ||||||||||||||||||||||||||||||||||
| order_svc --- o6 | ||||||||||||||||||||||||||||||||||
| order_svc --- o7 | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| subgraph "Product Service :8081" | ||||||||||||||||||||||||||||||||||
| product_svc([Product Service]) | ||||||||||||||||||||||||||||||||||
| p1["CRUD /api/v1/products"] | ||||||||||||||||||||||||||||||||||
| p2["POST /api/v1/products/{id}/reserve"] | ||||||||||||||||||||||||||||||||||
| p3["POST /api/v1/products/{id}/release"] | ||||||||||||||||||||||||||||||||||
| p4["GET /api/v1/products/search"] | ||||||||||||||||||||||||||||||||||
| p5["GET /health"] | ||||||||||||||||||||||||||||||||||
| product_svc --- p1 | ||||||||||||||||||||||||||||||||||
| product_svc --- p2 | ||||||||||||||||||||||||||||||||||
| product_svc --- p3 | ||||||||||||||||||||||||||||||||||
| product_svc --- p4 | ||||||||||||||||||||||||||||||||||
| product_svc --- p5 | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| subgraph "User Service :8082" | ||||||||||||||||||||||||||||||||||
| user_svc([User Service]) | ||||||||||||||||||||||||||||||||||
| u1["POST /api/v1/users"] | ||||||||||||||||||||||||||||||||||
| u2["GET /api/v1/users/{id}"] | ||||||||||||||||||||||||||||||||||
| u3["POST /api/v1/login"] | ||||||||||||||||||||||||||||||||||
| u4["GET /health"] | ||||||||||||||||||||||||||||||||||
| user_svc --- u1 | ||||||||||||||||||||||||||||||||||
| user_svc --- u2 | ||||||||||||||||||||||||||||||||||
| user_svc --- u3 | ||||||||||||||||||||||||||||||||||
| user_svc --- u4 | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| subgraph Datastores | ||||||||||||||||||||||||||||||||||
| dborders[(MySQL order_db)] | ||||||||||||||||||||||||||||||||||
| dbproducts[(MySQL product_db)] | ||||||||||||||||||||||||||||||||||
| dbusers[(MySQL user_db)] | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| sqs[(LocalStack SQS: order-events)] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| client --> order_svc | ||||||||||||||||||||||||||||||||||
| client --> product_svc | ||||||||||||||||||||||||||||||||||
| client --> user_svc | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| order_svc --> dborders | ||||||||||||||||||||||||||||||||||
| product_svc --> dbproducts | ||||||||||||||||||||||||||||||||||
| user_svc --> dbusers | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| order_svc --> user_svc | ||||||||||||||||||||||||||||||||||
| order_svc --> product_svc | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| order_svc --> sqs | ||||||||||||||||||||||||||||||||||
| # E-Commerce Microservices | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| [](https://python.org) | ||||||||||||||||||||||||||||||||||
| [](https://flask.palletsprojects.com) | ||||||||||||||||||||||||||||||||||
| [](https://docker.com) | ||||||||||||||||||||||||||||||||||
| [](https://keploy.io) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| A Python/Flask e-commerce backend using microservices, each with its own MySQL database, an API Gateway, and SQS event messaging via LocalStack - all wired together with Docker Compose. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Services | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| | Service | Port | Responsibility | | ||||||||||||||||||||||||||||||||||
| |---|---|---| | ||||||||||||||||||||||||||||||||||
| | API Gateway | `8083` | Single entry point - proxies all client requests | | ||||||||||||||||||||||||||||||||||
| | Order Service | `8080` | Order lifecycle, stock reservation, SQS events | | ||||||||||||||||||||||||||||||||||
| | Product Service | `8081` | Product catalog, inventory management | | ||||||||||||||||||||||||||||||||||
| | User Service | `8082` | Auth, JWT issuance, user accounts & addresses | | ||||||||||||||||||||||||||||||||||
| | LocalStack (SQS) | `4566` | Local AWS SQS - `order-events` queue | | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Quick Start | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| **Requires:** Docker Desktop (includes Compose) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||
| git clone https://github.com/keploy/ecommerce_sample_app.git | ||||||||||||||||||||||||||||||||||
| cd ecommerce_sample_app | ||||||||||||||||||||||||||||||||||
| docker compose up -d --build | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| That is it. On first boot the stack will: | ||||||||||||||||||||||||||||||||||
| - Run all DB migrations automatically | ||||||||||||||||||||||||||||||||||
| - Seed an admin user: `admin` / `admin123` | ||||||||||||||||||||||||||||||||||
| - Seed sample products (Laptop, Mouse) | ||||||||||||||||||||||||||||||||||
| - Create the `order-events` SQS queue | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| **Health check:** | ||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||
| curl http://localhost:8083/health | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| **Logs:** | ||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||
| docker compose logs -f | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| **Teardown:** | ||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||
| docker compose down -v # -v removes data volumes | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## API | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| All requests go through the gateway at `http://localhost:8083`. Every endpoint except `/api/v1/login` and `/health` requires `Authorization: Bearer <token>`. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
Comment on lines
+59
to
+60
|
||||||||||||||||||||||||||||||||||
| **Get a token:** | ||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||
| curl -s -X POST http://localhost:8083/api/v1/login \ | ||||||||||||||||||||||||||||||||||
| -H "Content-Type: application/json" \ | ||||||||||||||||||||||||||||||||||
| -d '{"username":"admin","password":"admin123"}' | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| | Service | Endpoints | | ||||||||||||||||||||||||||||||||||
| |---|---| | ||||||||||||||||||||||||||||||||||
| | **User** | `POST /api/v1/login` , `POST /api/v1/users` , `GET /api/v1/users/{id}` , `GET/POST /api/v1/users/{id}/addresses` | | ||||||||||||||||||||||||||||||||||
| | **Product** | `GET/POST /api/v1/products` , `GET/PUT/DELETE /api/v1/products/{id}` , `GET /api/v1/products/search` , `POST /api/v1/products/{id}/reserve` , `POST /api/v1/products/{id}/release` | | ||||||||||||||||||||||||||||||||||
| | **Order** | `GET/POST /api/v1/orders` , `GET /api/v1/orders/{id}` , `GET /api/v1/orders/{id}/details` , `POST /api/v1/orders/{id}/pay` , `POST /api/v1/orders/{id}/cancel` | | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Full OpenAPI specs: each service has an `openapi.yaml`. Import `postman/collection.gateway.json` + `postman/environment.local.json` for a ready-to-run Postman setup. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Architecture | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
| Client --> API Gateway (:8083) | ||||||||||||||||||||||||||||||||||
| |-- /users/* --> User Service (:8082) --> mysql-users (:3307) | ||||||||||||||||||||||||||||||||||
| |-- /products/* --> Product Service (:8081) --> mysql-products (:3308) | ||||||||||||||||||||||||||||||||||
| |-- /orders/* --> Order Service (:8080) --> mysql-orders (:3309) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+81
to
+84
|
||||||||||||||||||||||||||||||||||
| | | ||||||||||||||||||||||||||||||||||
| |-- calls User Service (validate user) | ||||||||||||||||||||||||||||||||||
| |-- calls Product Service (reserve / release stock) | ||||||||||||||||||||||||||||||||||
| +-- publishes --> SQS order-events (LocalStack :4566) | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| **Key behaviours:** | ||||||||||||||||||||||||||||||||||
| - `POST /orders` validates the user, reserves product stock, persists the order, then emits an `ORDER_CREATED` event to SQS. | ||||||||||||||||||||||||||||||||||
| - Supports `Idempotency-Key` header on order creation to prevent duplicates. | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
| - Supports `Idempotency-Key` header on order creation to prevent duplicates. | |
| - `POST /orders` accepts an `Idempotency-Key` header; this is stored with a DB unique constraint on `idempotency_key`, so reusing the same key currently triggers a 500 error from the unique-constraint violation rather than returning the original order. |
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These ‘Key behaviours’ bullets don’t match the implementation: the order endpoint is /api/v1/orders (not /orders), and the SQS event types emitted by order_service are order_created / order_cancelled (lowercase), not ORDER_CREATED / ORDER_CANCELLED. Align the README wording with the actual routes/event payloads.
| - `POST /orders` validates the user, reserves product stock, persists the order, then emits an `ORDER_CREATED` event to SQS. | |
| - Supports `Idempotency-Key` header on order creation to prevent duplicates. | |
| - Cancelling an order releases reserved stock and emits `ORDER_CANCELLED`. | |
| - `POST /api/v1/orders` validates the user, reserves product stock, persists the order, then emits an `order_created` event to SQS. | |
| - Supports `Idempotency-Key` header on order creation to prevent duplicates. | |
| - Cancelling an order releases reserved stock and emits `order_cancelled`. |
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Coverage reports are written to coverage/” is incomplete/misleading: the coverage data files are written under the top-level coverage/ volume, but the HTML output is generated under each service’s */coverage/htmlcov/ directory. Consider clarifying where to find the HTML report.
| Coverage reports are written to `coverage/` during test runs. | |
| Coverage data is written to the shared `coverage/` volume during test runs, while per-service HTML reports are generated under each service’s `*/coverage/htmlcov/` directory (for example, `order_service/coverage/htmlcov/index.html`). |
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section says variables are “Set in docker-compose.yml”, but JWT_SECRET is not actually set in docker-compose.yml (services fall back to the in-code default), and the seeded admin password comes from the SQL migration (hard-coded admin/admin123), not the ADMIN_PASSWORD env var. Update the table/wording to reflect the real defaults and which env vars are actually consumed.
| Set in `docker-compose.yml`. Key variables: | |
| | Variable | Default | Note | | |
| |---|---|---| | |
| | `JWT_SECRET` | `dev-secret-change-me` | **Must change in production** | | |
| | `DB_HOST / DB_USER / DB_PASSWORD / DB_NAME` | per-service | Each service owns its own DB | | |
| | `AWS_ENDPOINT` | `http://localstack:4566` | Routes SQS traffic to LocalStack | | |
| | `ADMIN_PASSWORD` | `admin123` | Seeded admin credentials | | |
| Configuration & defaults (from env, code, and migrations): | |
| | Variable | Default | Note | | |
| |---|---|---| | |
| | `JWT_SECRET` | `dev-secret-change-me` (in-code) | Used by the User Service for JWT signing; override via `JWT_SECRET` env var (**must change in production**) | | |
| | `DB_HOST / DB_USER / DB_PASSWORD / DB_NAME` | per-service | Each service owns its own DB; values typically set via `docker-compose.yml` | | |
| | `AWS_ENDPOINT` | `http://localstack:4566` | Routes SQS traffic to LocalStack (e.g. `http://localstack:4566` in Docker) | | |
| | Admin credentials | `admin / admin123` (SQL migration) | Initial admin user is seeded by migration; current seeding does not read `ADMIN_PASSWORD` env var | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curl http://localhost:8083/healthwon’t work as written: the API gateway implementation doesn’t expose a/healthroute (and none of the Flask apps define it). Update the README to point to an actual unauthenticated endpoint (e.g.POST /api/v1/login) or add/healthhandlers in code (and keep docs consistent).