Skip to content

Commit 30ec9da

Browse files
committed
docs: initialize project wiki with architecture and request flow documentation and add MIT license
1 parent 00982fc commit 30ec9da

11 files changed

Lines changed: 1183 additions & 2 deletions

File tree

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 FairDrop
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
HOST ?= http://localhost:8080
2+
HOST_DIRECT ?= http://localhost:8000
23

34
.PHONY: stress-test oversell-test orders-test mixed-test ratelimit-test s3-test
5+
.PHONY: stress-test-direct oversell-test-direct orders-test-direct mixed-test-direct ratelimit-test-direct s3-test-direct
6+
7+
# === Through nginx gateway (port 8080) ===
48

59
stress-test:
610
uv run locust \
@@ -56,3 +60,60 @@ s3-test:
5660
--spawn-rate 10 \
5761
--run-time 20s \
5862
--host $(HOST)
63+
64+
# === Direct to FastAPI, bypassing nginx (port 8000) ===
65+
66+
stress-test-direct:
67+
uv run locust \
68+
-f load_tests/locustfile.py \
69+
--headless \
70+
--users 500 \
71+
--spawn-rate 100 \
72+
--run-time 60s \
73+
--host $(HOST_DIRECT)
74+
75+
oversell-test-direct:
76+
DB_HOST=localhost uv run python scripts/seed_oversell_product.py
77+
uv run locust \
78+
-f load_tests/locustfile_oversell.py \
79+
--headless \
80+
--users 100 \
81+
--spawn-rate 50 \
82+
--run-time 60s \
83+
--host $(HOST_DIRECT)
84+
85+
orders-test-direct:
86+
uv run locust \
87+
-f load_tests/locustfile_orders.py \
88+
--headless \
89+
--users 100 \
90+
--spawn-rate 50 \
91+
--run-time 60s \
92+
--host $(HOST_DIRECT)
93+
94+
mixed-test-direct:
95+
uv run locust \
96+
-f load_tests/locustfile_mixed.py \
97+
--headless \
98+
--users 100 \
99+
--spawn-rate 50 \
100+
--run-time 60s \
101+
--host $(HOST_DIRECT)
102+
103+
ratelimit-test-direct:
104+
uv run locust \
105+
-f load_tests/locustfile_ratelimit.py \
106+
--headless \
107+
--users 1 \
108+
--spawn-rate 1 \
109+
--run-time 15s \
110+
--host $(HOST_DIRECT)
111+
112+
s3-test-direct:
113+
uv run locust \
114+
-f load_tests/locustfile_s3.py \
115+
--headless \
116+
--users 50 \
117+
--spawn-rate 10 \
118+
--run-time 20s \
119+
--host $(HOST_DIRECT)

README.md

Lines changed: 747 additions & 2 deletions
Large diffs are not rendered by default.

docs/wiki/Architecture.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# System Architecture
2+
3+
FairDrop uses a modular monolith architecture with nginx gateway, async FastAPI services, PostgreSQL, Redis, MinIO, and ARQ workers.
4+
5+
```mermaid
6+
flowchart TB
7+
User["Client B2B"]
8+
Attacker["Botnet"]
9+
NginxHost["Nginx 20rps"]
10+
NginxDocker["Nginx proxy"]
11+
UserAPI["user module"]
12+
BuyerAPI["buyer_user module"]
13+
SellerAPI["seller_user module"]
14+
ExternalAPI["external module"]
15+
InvAPI["inventory module"]
16+
OrderAPI["orders module"]
17+
MediaAPI["media module"]
18+
Worker["ARQ worker"]
19+
Postgres[("PostgreSQL 15")]
20+
Redis[("Redis")]
21+
MinIO[("MinIO S3")]
22+
Prometheus["Prometheus"]
23+
Grafana["Grafana"]
24+
25+
User --> NginxHost
26+
Attacker --> NginxHost
27+
NginxHost --> NginxDocker
28+
NginxDocker --> UserAPI
29+
NginxDocker --> BuyerAPI
30+
NginxDocker --> SellerAPI
31+
NginxDocker --> ExternalAPI
32+
NginxDocker --> InvAPI
33+
NginxDocker --> OrderAPI
34+
NginxDocker --> MediaAPI
35+
36+
UserAPI --> Redis
37+
BuyerAPI --> Redis
38+
SellerAPI --> Redis
39+
ExternalAPI --> Redis
40+
InvAPI --> Redis
41+
OrderAPI --> Redis
42+
MediaAPI --> Redis
43+
44+
UserAPI --> Postgres
45+
BuyerAPI --> Postgres
46+
SellerAPI --> Postgres
47+
ExternalAPI --> Postgres
48+
InvAPI --> Postgres
49+
OrderAPI --> Postgres
50+
MediaAPI --> Postgres
51+
52+
Worker --> Redis
53+
Worker --> Postgres
54+
55+
MediaAPI -.-> User
56+
User -.-> MinIO
57+
MinIO -.-> MediaAPI
58+
Worker -.-> Postgres
59+
Worker -.-> MinIO
60+
UserAPI -.-> Prometheus
61+
InvAPI -.-> Prometheus
62+
OrderAPI -.-> Prometheus
63+
MediaAPI -.-> Prometheus
64+
Prometheus --> Grafana
65+
```
66+
67+
## Components
68+
69+
| Layer | Component | Description |
70+
|---|---|---|
71+
| **Perimeter** | Nginx Gateway | Rate limiting 20r/s, IP whitelist for webhooks |
72+
| **App** | FastAPI | 8 modules: user, buyer_user, seller_user, external, inventory, orders, media, payments |
73+
| **Background** | ARQ Worker | Cron cleanup expired reservations, image sanitization |
74+
| **Storage** | PostgreSQL 15 | Async SQLAlchemy, pool 200+ |
75+
| **Cache** | Redis | Lua rate limiting, ARQ queues, idempotency keys |
76+
| **Storage** | MinIO S3 | Object storage for media |
77+
| **Monitoring** | Prometheus + Grafana | Metrics via prometheus-fastapi-instrumentator |

docs/wiki/Home.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# FairDrop Wiki
2+
3+
Welcome to the FairDrop documentation wiki. This project is a B2B/B2C dropshipping platform with async modular monolith architecture.
4+
5+
## Navigation
6+
7+
| Page | Description |
8+
|---|---|
9+
| [Architecture](Architecture) | System architecture diagram |
10+
| [Request Flow](Request-Flow) | Inventory reservation flow |
11+
12+
## License
13+
14+
This project is licensed under the [MIT License](https://github.com/codewithme-py/FairDrop/blob/main/LICENSE).
15+
16+
## Quick Links
17+
18+
- [Source Code](https://github.com/codewithme-py/FairDrop)
19+
- [README](https://github.com/codewithme-py/FairDrop#readme)
20+
- [Actions](https://github.com/codewithme-py/FairDrop/actions)

docs/wiki/Request-Flow.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Request Flow — Inventory Reservation
2+
3+
Sequence diagram showing the complete inventory reservation flow including rate limiting, idempotency, and ARQ cleanup.
4+
5+
```mermaid
6+
sequenceDiagram
7+
autonumber
8+
participant C as Client
9+
participant N as Nginx Gateway
10+
participant A as FastAPI App
11+
participant R as Redis
12+
participant DB as Postgres
13+
14+
Note over C,N: Rate Limiting Nginx layer
15+
C->>N: POST /api/v1/inventory/reserve
16+
N->>N: limit_req_zone 20r/s global
17+
alt Rate exceeded at Nginx
18+
N-->>C: 429 Too Many Requests
19+
else OK
20+
N->>A: Forward to app port 8000
21+
end
22+
23+
Note over A,R: Rate Limiting Lua layer
24+
A->>R: Lua script per-user and global
25+
R-->>A: OK limit not reached
26+
27+
Note over A,R: Idempotency check
28+
A->>R: GET idempotency key 24h TTL
29+
alt Key exists
30+
R-->>A: Return cached response
31+
A-->>C: 200 OK cached
32+
else
33+
A->>R: SET idempotency key
34+
end
35+
36+
Note over A,DB: Reserve transaction
37+
A->>DB: BEGIN Transaction
38+
A->>DB: SELECT Product FOR UPDATE
39+
alt Stock Available
40+
A->>DB: INSERT Reservation status PENDING expires 15 min
41+
A->>DB: UPDATE Product qty_available minus qty_reserved
42+
A->>DB: COMMIT Transaction
43+
A->>R: Cache response
44+
A-->>C: 201 Created reserved 15 min
45+
else Out of Stock
46+
A->>DB: ROLLBACK
47+
A-->>C: 409 Conflict Sold Out
48+
end
49+
50+
Note over A,DB: ARQ Worker cleanup expired reservations
51+
loop Cron every 60 seconds
52+
A->>DB: SELECT Reservation status PENDING expired
53+
alt Found expired
54+
A->>DB: FOR UPDATE Reservation plus Product
55+
A->>DB: Product.qty_available plus Reservation.qty_reserved
56+
A->>DB: Reservation.status equals EXPIRED
57+
opt order_id is set
58+
A->>DB: cancel_order_by_system
59+
end
60+
A->>DB: COMMIT
61+
end
62+
end
63+
```
64+
65+
## Flow Steps
66+
67+
1. **Nginx rate limit** — global 20r/s filter at gateway level
68+
2. **Lua rate limit** — per-user 10 RPS + global 1000 RPS in Redis
69+
3. **Idempotency check** — Redis cache with 24h TTL prevents duplicate orders
70+
4. **Reserve transaction**`SELECT FOR UPDATE` locks product row, creates PENDING reservation for 15 min
71+
5. **ARQ cleanup** — cron job runs every 60 seconds, releases expired reservations and returns stock

docs/wiki/_Sidebar.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# FairDrop Wiki
2+
3+
- [[Home| Home]]
4+
- [[Architecture| System Architecture]]
5+
- [[Request-Flow| Request Flow]]
6+
7+
---
8+
9+
[View Source Code](https://github.com/codewithme-py/FairDrop)

wiki/Architecture.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# System Architecture
2+
3+
FairDrop uses a modular monolith architecture with nginx gateway, async FastAPI services, PostgreSQL, Redis, MinIO, and ARQ workers.
4+
5+
```mermaid
6+
flowchart TB
7+
User["Client B2B"]
8+
Attacker["Botnet"]
9+
NginxHost["Nginx 20rps"]
10+
NginxDocker["Nginx proxy"]
11+
UserAPI["user module"]
12+
BuyerAPI["buyer_user module"]
13+
SellerAPI["seller_user module"]
14+
ExternalAPI["external module"]
15+
InvAPI["inventory module"]
16+
OrderAPI["orders module"]
17+
MediaAPI["media module"]
18+
Worker["ARQ worker"]
19+
Postgres[("PostgreSQL 15")]
20+
Redis[("Redis")]
21+
MinIO[("MinIO S3")]
22+
Prometheus["Prometheus"]
23+
Grafana["Grafana"]
24+
25+
User --> NginxHost
26+
Attacker --> NginxHost
27+
NginxHost --> NginxDocker
28+
NginxDocker --> UserAPI
29+
NginxDocker --> BuyerAPI
30+
NginxDocker --> SellerAPI
31+
NginxDocker --> ExternalAPI
32+
NginxDocker --> InvAPI
33+
NginxDocker --> OrderAPI
34+
NginxDocker --> MediaAPI
35+
36+
UserAPI --> Redis
37+
BuyerAPI --> Redis
38+
SellerAPI --> Redis
39+
ExternalAPI --> Redis
40+
InvAPI --> Redis
41+
OrderAPI --> Redis
42+
MediaAPI --> Redis
43+
44+
UserAPI --> Postgres
45+
BuyerAPI --> Postgres
46+
SellerAPI --> Postgres
47+
ExternalAPI --> Postgres
48+
InvAPI --> Postgres
49+
OrderAPI --> Postgres
50+
MediaAPI --> Postgres
51+
52+
Worker --> Redis
53+
Worker --> Postgres
54+
55+
MediaAPI -.-> User
56+
User -.-> MinIO
57+
MinIO -.-> MediaAPI
58+
Worker -.-> Postgres
59+
Worker -.-> MinIO
60+
UserAPI -.-> Prometheus
61+
InvAPI -.-> Prometheus
62+
OrderAPI -.-> Prometheus
63+
MediaAPI -.-> Prometheus
64+
Prometheus --> Grafana
65+
```
66+
67+
## Components
68+
69+
| Layer | Component | Description |
70+
|---|---|---|
71+
| **Perimeter** | Nginx Gateway | Rate limiting 20r/s, IP whitelist for webhooks |
72+
| **App** | FastAPI | 8 modules: user, buyer_user, seller_user, external, inventory, orders, media, payments |
73+
| **Background** | ARQ Worker | Cron cleanup expired reservations, image sanitization |
74+
| **Storage** | PostgreSQL 15 | Async SQLAlchemy, pool 200+ |
75+
| **Cache** | Redis | Lua rate limiting, ARQ queues, idempotency keys |
76+
| **Storage** | MinIO S3 | Object storage for media |
77+
| **Monitoring** | Prometheus + Grafana | Metrics via prometheus-fastapi-instrumentator |

wiki/Home.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# FairDrop Wiki
2+
3+
Welcome to the FairDrop documentation wiki. This project is a B2B/B2C dropshipping platform with async modular monolith architecture.
4+
5+
## Navigation
6+
7+
| Page | Description |
8+
|---|---|
9+
| [Architecture](Architecture) | System architecture diagram |
10+
| [Request Flow](Request-Flow) | Inventory reservation flow |
11+
12+
## License
13+
14+
This project is licensed under the [MIT License](https://github.com/codewithme-py/FairDrop/blob/main/LICENSE).
15+
16+
## Quick Links
17+
18+
- [Source Code](https://github.com/codewithme-py/FairDrop)
19+
- [README](https://github.com/codewithme-py/FairDrop#readme)
20+
- [Actions](https://github.com/codewithme-py/FairDrop/actions)

0 commit comments

Comments
 (0)