Merge pull request #51 from nprasad2077/limits

limits
This commit is contained in:
2026-05-29 00:46:53 -05:00
committed by GitHub
9 changed files with 1790 additions and 42 deletions
Vendored
BIN
View File
Binary file not shown.
+7
View File
@@ -34,3 +34,10 @@ docs/restore_dump_remote.md
./docs/restore_dump_remote.md
docs/notes/conversation_1.md
docs/notes/conversation_2.md
docs/kiro.md
docs/cloudflare.json
docs/notes
docs/postman
+42 -41
View File
@@ -44,35 +44,35 @@ A high-performance NBA statistics REST API built with Go (Fiber), PostgreSQL, an
## API Endpoints
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/games` | Game data with box scores, line scores, team/player stats |
| GET | `/api/playeradvancedstats` | Advanced stats (PER, WS, VORP, BPM, etc.) |
| GET | `/api/playertotals` | Season totals (points, rebounds, assists, etc.) |
| GET | `/api/playershotchart` | Shot chart coordinate data |
| GET | `/swagger/*` | Interactive Swagger UI documentation |
| GET | `/metrics` | Prometheus metrics endpoint |
| POST | `/admin/keys` | Create API key (requires `X-Admin-Secret` header) |
| Method | Path | Description |
| ------ | -------------------------- | --------------------------------------------------------- |
| GET | `/api/games` | Game data with box scores, line scores, team/player stats |
| GET | `/api/playeradvancedstats` | Advanced stats (PER, WS, VORP, BPM, etc.) |
| GET | `/api/playertotals` | Season totals (points, rebounds, assists, etc.) |
| GET | `/api/playershotchart` | Shot chart coordinate data |
| GET | `/swagger/*` | Interactive Swagger UI documentation |
| GET | `/metrics` | Prometheus metrics endpoint |
| POST | `/admin/keys` | Create API key (requires `X-Admin-Secret` header) |
### Query Parameters (all data endpoints)
| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | int | Page number (default: 1) |
| `pageSize` | int | Results per page (default: 20) |
| `sortBy` | string | Field to sort by (varies per endpoint) |
| `ascending` | bool | Sort direction (default: false / descending) |
| `season` | int | Filter by season year (e.g., 2025) |
| `team` | string | Filter by team abbreviation (e.g., LAL, BOS) |
| `playerId` | string | Filter by player ID (e.g., jamesle01) |
| `isPlayoff` | bool | Filter for playoff stats |
| Parameter | Type | Description |
| ----------- | ------ | -------------------------------------------- |
| `page` | int | Page number (default: 1) |
| `pageSize` | int | Results per page (default: 20) |
| `sortBy` | string | Field to sort by (varies per endpoint) |
| `ascending` | bool | Sort direction (default: false / descending) |
| `season` | int | Filter by season year (e.g., 2025) |
| `team` | string | Filter by team abbreviation (e.g., LAL, BOS) |
| `playerId` | string | Filter by player ID (e.g., jamesle01) |
| `isPlayoff` | bool | Filter for playoff stats |
#### Games-specific parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| `date` | string | Filter by date (YYYY-MM-DD) |
| `gameId` | string | Filter by specific game ID |
| Parameter | Type | Description |
| --------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `date` | string | Filter by date (YYYY-MM-DD) |
| `gameId` | string | Filter by specific game ID |
| `include` | string | Comma-separated associations to preload: `lineScores`, `playerGameBasicStats`, `playerGameAdvStats`, `teamGameBasicStats`, `teamGameAdvStats` |
### Example Requests
@@ -149,14 +149,14 @@ make up
Services will be available at:
| Service | URL |
|---------|-----|
| API (via NGINX) | http://localhost:8081 |
| Prometheus | http://localhost:9090 |
| Grafana | http://localhost:3001 (admin/testing) |
| API instance 1 (direct) | http://localhost:5001 |
| API instance 2 (direct) | http://localhost:5002 |
| API instance 3 (direct) | http://localhost:5003 |
| Service | URL |
| ----------------------- | --------------------------------------- |
| API (via NGINX) | <http://localhost:8081> |
| Prometheus | <http://localhost:9090> |
| Grafana | <http://localhost:3001> (admin/testing) |
| API instance 1 (direct) | <http://localhost:5001> |
| API instance 2 (direct) | <http://localhost:5002> |
| API instance 3 (direct) | <http://localhost:5003> |
### Importing Data
@@ -167,6 +167,7 @@ docker-compose -f docker-compose.local.yml run --rm db-init
```
This runs `main.go` with the `import-data` argument, which:
1. Runs all GORM AutoMigrate operations
2. Scrapes Basketball Reference for player advanced stats, totals, game schedules, and box scores
3. Upserts all data into PostgreSQL
@@ -238,14 +239,14 @@ go run loadtest.go -n 100 -c 10 -url "http://localhost:8080/api/playeradvancedst
## Tech Stack
| Component | Technology |
|-----------|-----------|
| Language | Go 1.23+ |
| Framework | Fiber v2 |
| ORM | GORM |
| Database | PostgreSQL 15 |
| Scraping | goquery |
| Load Balancer | NGINX |
| Monitoring | Prometheus + Grafana |
| Docs | Swagger (swaggo) |
| Component | Technology |
| ---------------- | ----------------------- |
| Language | Go 1.23+ |
| Framework | Fiber v2 |
| ORM | GORM |
| Database | PostgreSQL 15 |
| Scraping | goquery |
| Load Balancer | NGINX |
| Monitoring | Prometheus + Grafana |
| Docs | Swagger (swaggo) |
| Containerization | Docker + Docker Compose |
+3
View File
@@ -240,6 +240,9 @@ func GetGames(db *gorm.DB) fiber.Handler {
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("pageSize", 20)
if pageSize > 50 {
pageSize = 50
}
offset := (page - 1) * pageSize
var games []models.Game
@@ -150,6 +150,9 @@ func GetAllAdvancedPlayerStats(db *gorm.DB) fiber.Handler {
// --- PAGINATION ---
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("pageSize", 20)
if pageSize > 50 {
pageSize = 50
}
offset := (page - 1) * pageSize
// --- SORTING ---
+3
View File
@@ -150,6 +150,9 @@ func GetPlayerTotalStats(db *gorm.DB) fiber.Handler {
team := c.Query("team")
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("pageSize", 20)
if pageSize > 50 {
pageSize = 50
}
// --- SORTING ---
sortByParam := c.Query("sortBy", "points")
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
cat > /data/nba-go-config/nginx/nginx.conf << 'EOF'
user nginx;
events {
worker_connections 1024;
}
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=100m inactive=5m;
map $http_referer $blocked_referer {
default 0;
"~*nbasalarymodel\.xyz" 1;
"~*kacpertheater\.github\.io" 1;
}
upstream go_backend {
server api1:5000;
server api2:5000;
server api3:5000;
}
server {
listen 8080;
access_log /dev/stdout;
error_log /dev/stderr;
if ($blocked_referer) {
return 403;
}
location /api/ {
proxy_cache api_cache;
proxy_cache_valid 200 30s;
proxy_cache_key "$request_uri";
proxy_cache_use_stale error timeout updating;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://go_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://go_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
EOF
docker exec 4c3368863bdc nginx -s reload