feat: connect backend to postgres via docker network
This commit is contained in:
481
SOP.md
Normal file
481
SOP.md
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
# SOP.md — Prototipo Gioco Carte (Server Docker + Client Test)
|
||||||
|
|
||||||
|
> Obiettivo: realizzare un prototipo end-to-end dove:
|
||||||
|
> - Utente si registra/login con email+password
|
||||||
|
> - Ha una valuta (Gold) con cui apre bauli
|
||||||
|
> - Aprendo un baule ottiene carte con rarità
|
||||||
|
> - La collezione è "unique-only": la carta viene salvata solo se non già posseduta
|
||||||
|
> - Se la carta è già posseduta: conversione in Gold (o altra regola definita)
|
||||||
|
> - I giocatori possono vedere la collezione pubblica di altri giocatori
|
||||||
|
> - Server e DB girano su Docker
|
||||||
|
> - Esiste un client temporaneo testabile (CLI o Postman) per test E2E
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0) Decisioni bloccanti (DA DEFINIRE PRIMA DI CODIFICARE)
|
||||||
|
Compilare questa sezione PRIMA di procedere.
|
||||||
|
|
||||||
|
- [ ] STACK_BACKEND: TODO (FastAPI / NestJS)
|
||||||
|
- [ ] DB: PostgreSQL (default)
|
||||||
|
- [ ] ORM: TODO (SQLAlchemy+Alembic / Prisma / TypeORM)
|
||||||
|
- [ ] AUTH: TODO (JWT access + refresh / solo access)
|
||||||
|
- [ ] CLIENT_TEST: TODO (CLI Python / Postman / entrambi)
|
||||||
|
- [ ] CHEST:
|
||||||
|
- gold_initial: 1000
|
||||||
|
- chest_cost: 100
|
||||||
|
- cards_per_open: 3
|
||||||
|
- rarities: Common 70%, Rare 25%, Legendary 5%
|
||||||
|
- duplicate_conversion_gold: 20
|
||||||
|
- [ ] PRIVACY:
|
||||||
|
- collection_public_default: true
|
||||||
|
|
||||||
|
> Regola: se un valore è “TODO” non procedere oltre senza definirlo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1) Regole Architetturali (NON negoziabili)
|
||||||
|
- Tutta la logica RNG e assegnazione premi sta nel backend (mai nel client).
|
||||||
|
- Il backend è l’unica sorgente di verità. Il client visualizza e chiama API.
|
||||||
|
- L’apertura baule deve essere:
|
||||||
|
- atomica (transazione DB)
|
||||||
|
- idempotente (retry rete non deve duplicare premi né spesa)
|
||||||
|
- La collezione non deve avere duplicati:
|
||||||
|
- vincolo DB: PRIMARY KEY (user_id, card_id)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2) Convenzioni Repo e Commit
|
||||||
|
### 2.1 Struttura repository
|
||||||
|
Creare repo con questa struttura:
|
||||||
|
|
||||||
|
card-game/
|
||||||
|
- backend/
|
||||||
|
- client-test/ (CLI o Postman)
|
||||||
|
- infra/
|
||||||
|
- spec/
|
||||||
|
- docker-compose.yml
|
||||||
|
- .env.example
|
||||||
|
- README.md
|
||||||
|
- SOP.md
|
||||||
|
|
||||||
|
### 2.2 Regole commit
|
||||||
|
- Ogni step sotto corrisponde a 1 commit (o più commit piccoli) con un messaggio chiaro:
|
||||||
|
- feat: ...
|
||||||
|
- test: ...
|
||||||
|
- chore: ...
|
||||||
|
- Ogni commit deve avere un “Gate” (test di verifica) che deve passare.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3) Stack locale con Docker (Backend + DB)
|
||||||
|
### 3.1 File obbligatori
|
||||||
|
- docker-compose.yml
|
||||||
|
- backend/Dockerfile
|
||||||
|
- backend/.dockerignore
|
||||||
|
- .env.example
|
||||||
|
|
||||||
|
### 3.2 Variabili ambiente minime (.env)
|
||||||
|
Definire:
|
||||||
|
- APP_ENV=local
|
||||||
|
- DB_HOST=db
|
||||||
|
- DB_PORT=5432
|
||||||
|
- DB_NAME=cardgame
|
||||||
|
- DB_USER=cardgame
|
||||||
|
- DB_PASSWORD=cardgame
|
||||||
|
- JWT_SECRET=change-me
|
||||||
|
- JWT_ACCESS_TTL_MIN=15
|
||||||
|
- JWT_REFRESH_TTL_DAYS=30
|
||||||
|
|
||||||
|
> Non committare mai `.env` vero. Solo `.env.example`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# STEPS (commit-based)
|
||||||
|
|
||||||
|
## STEP 01 — Bootstrap repo + Docker “Hello World”
|
||||||
|
### Obiettivo
|
||||||
|
- `docker compose up --build` avvia tutto
|
||||||
|
- backend espone `GET /health` → `{ "status": "ok" }`
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
1) Creare docker-compose.yml con:
|
||||||
|
- service `db` (postgres)
|
||||||
|
- service `api` (backend)
|
||||||
|
2) Implementare endpoint `/health`
|
||||||
|
3) Documentare README con comandi minimi
|
||||||
|
|
||||||
|
### Output
|
||||||
|
- docker-compose.yml
|
||||||
|
- backend/Dockerfile
|
||||||
|
- backend/app/main.(py|ts)
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: bootstrap docker compose and health endpoint`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- Comando: `docker compose up --build`
|
||||||
|
- Verifica:
|
||||||
|
- `curl http://localhost:8000/health`
|
||||||
|
- Risposta deve essere `{"status":"ok"}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 02 — Connessione DB + endpoint db-check
|
||||||
|
### Obiettivo
|
||||||
|
Backend connesso realmente a Postgres.
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
1) Aggiungere driver DB e configurazione.
|
||||||
|
2) Implementare `GET /db-check` che esegue `SELECT 1`.
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: add database connection and db-check endpoint`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- `curl http://localhost:8000/db-check`
|
||||||
|
- Risposta: `{ "db": "ok" }`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 03 — Schema DB v1 (tabelle core)
|
||||||
|
### Obiettivo
|
||||||
|
Creare schema DB minimo completo per il prototipo.
|
||||||
|
|
||||||
|
### Tabelle richieste (v1)
|
||||||
|
#### users
|
||||||
|
- id (uuid / serial)
|
||||||
|
- email (unique, not null)
|
||||||
|
- password_hash
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### user_profiles
|
||||||
|
- user_id (PK/FK users.id)
|
||||||
|
- nickname (unique, not null)
|
||||||
|
- is_collection_public (bool, default true)
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### wallets
|
||||||
|
- user_id (PK/FK)
|
||||||
|
- balance (int, not null)
|
||||||
|
|
||||||
|
#### wallet_transactions
|
||||||
|
- id
|
||||||
|
- user_id
|
||||||
|
- type (CREDIT/DEBIT)
|
||||||
|
- amount
|
||||||
|
- reason (REGISTER_BONUS, CHEST_OPEN, DUPLICATE_CONVERT, etc.)
|
||||||
|
- reference_id (nullable, e.g. chest_open_id)
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### cards (catalogo)
|
||||||
|
- id (string or uuid)
|
||||||
|
- name
|
||||||
|
- rarity (COMMON/RARE/LEGENDARY)
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### chests (catalogo)
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- cost_gold
|
||||||
|
- cards_per_open
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### user_cards (collezione unique-only)
|
||||||
|
- user_id
|
||||||
|
- card_id
|
||||||
|
- obtained_at
|
||||||
|
- PRIMARY KEY (user_id, card_id)
|
||||||
|
|
||||||
|
#### chest_opens (audit)
|
||||||
|
- id
|
||||||
|
- user_id
|
||||||
|
- chest_id
|
||||||
|
- spent_gold
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### chest_open_items (audit dettagli)
|
||||||
|
- id
|
||||||
|
- chest_open_id
|
||||||
|
- card_id (nullable se conversion-only)
|
||||||
|
- rarity
|
||||||
|
- outcome_type (NEW / CONVERTED)
|
||||||
|
- converted_gold (nullable)
|
||||||
|
- created_at
|
||||||
|
|
||||||
|
#### idempotency_keys
|
||||||
|
- key (string)
|
||||||
|
- user_id
|
||||||
|
- endpoint (e.g. "POST:/chests/{id}/open")
|
||||||
|
- response_body (json/text)
|
||||||
|
- created_at
|
||||||
|
- UNIQUE (key, user_id, endpoint)
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
- Implementare migrazioni (consigliato) o create_all (solo prototipo).
|
||||||
|
- Assicurare vincoli unici e FK.
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: add database schema v1`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- Avviare stack e verificare che tabelle esistano (psql o query).
|
||||||
|
- Verificare vincolo UNIQUE email e nickname.
|
||||||
|
- Verificare PK composita su user_cards.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 04 — Seed catalogo (cards + chests)
|
||||||
|
### Obiettivo
|
||||||
|
Popolare catalogo con dati minimi.
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
- Inserire almeno:
|
||||||
|
- 10 cards (mix rarità)
|
||||||
|
- 1 chest base (cost=100, cards_per_open=3)
|
||||||
|
- Seed deve essere ripetibile (non duplicare se rilanciato).
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: seed initial catalog (cards, chests)`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- `GET /catalog/cards` ritorna lista > 0
|
||||||
|
- `GET /catalog/chests` ritorna lista > 0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 05 — Auth: register + login (email/password)
|
||||||
|
### Obiettivo
|
||||||
|
Utente può registrarsi e loggarsi.
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
Implementare:
|
||||||
|
- `POST /auth/register`:
|
||||||
|
- valida email e password (minimo)
|
||||||
|
- hash password
|
||||||
|
- crea user
|
||||||
|
- crea profile con nickname (TODO: decidere quando si setta nickname)
|
||||||
|
- crea wallet con gold_initial
|
||||||
|
- crea wallet_transaction REGISTER_BONUS
|
||||||
|
- `POST /auth/login`:
|
||||||
|
- verifica credenziali
|
||||||
|
- emette token (access + refresh se previsto)
|
||||||
|
|
||||||
|
> Nota: nickname
|
||||||
|
- Opzione A: richiesto in register (consigliato per social immediato)
|
||||||
|
- Opzione B: scelto dopo login (richiede endpoint `/me/profile` update)
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: implement register and login`
|
||||||
|
|
||||||
|
### Gate / Test (manuale)
|
||||||
|
- Register nuovo: 201
|
||||||
|
- Register email già usata: 409
|
||||||
|
- Login corretto: 200 + token
|
||||||
|
- Login password errata: 401
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 06 — Endpoint me: wallet + collection + profile
|
||||||
|
### Obiettivo
|
||||||
|
Utente autenticato può vedere:
|
||||||
|
- saldo
|
||||||
|
- collezione
|
||||||
|
- profilo
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
Implementare:
|
||||||
|
- `GET /me/wallet`
|
||||||
|
- `GET /me/collection`
|
||||||
|
- `GET /me/profile`
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: add me endpoints (wallet, collection, profile)`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- Dopo register/login:
|
||||||
|
- wallet = gold_initial
|
||||||
|
- collection = []
|
||||||
|
- profile contiene nickname
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 07 — Core: Open Chest (transazione + unique-only + conversione)
|
||||||
|
### Obiettivo
|
||||||
|
Endpoint che apre il baule con logica corretta e audit completo.
|
||||||
|
|
||||||
|
### Endpoint
|
||||||
|
- `POST /chests/{chestId}/open`
|
||||||
|
Header:
|
||||||
|
- Authorization: Bearer <access_token>
|
||||||
|
- Idempotency-Key: <uuid>
|
||||||
|
|
||||||
|
### Algoritmo (obbligatorio)
|
||||||
|
Dentro una transazione DB:
|
||||||
|
1) Validare chestId
|
||||||
|
2) Verificare saldo >= cost
|
||||||
|
3) Debit saldo (wallet)
|
||||||
|
4) Per i=1..cards_per_open:
|
||||||
|
4.1) Roll rarità secondo pesi
|
||||||
|
4.2) Selezionare una carta casuale tra quelle di quella rarità NON possedute dall’utente
|
||||||
|
- Se pool vuoto:
|
||||||
|
- outcome = CONVERTED (converted_gold = duplicate_conversion_gold)
|
||||||
|
- credit wallet
|
||||||
|
- wallet_transaction DUPLICATE_CONVERT
|
||||||
|
- Se pool non vuoto:
|
||||||
|
- inserire in user_cards (PK impedisce dup)
|
||||||
|
- outcome = NEW
|
||||||
|
5) Salvare chest_opens + chest_open_items
|
||||||
|
6) Commit
|
||||||
|
|
||||||
|
### Idempotenza
|
||||||
|
- Se la stessa Idempotency-Key per lo stesso user+endpoint è già stata usata:
|
||||||
|
- ritornare ESATTAMENTE la response salvata
|
||||||
|
- NON scalare saldo
|
||||||
|
- NON creare nuovi record
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: implement open chest with transaction, unique-only, conversion, audit`
|
||||||
|
|
||||||
|
### Gate / Test (manuale)
|
||||||
|
Caso A (happy path):
|
||||||
|
- wallet iniziale 1000
|
||||||
|
- open chest
|
||||||
|
- wallet diminuisce di 100 (+ eventuali conversioni)
|
||||||
|
- collection cresce con nuove carte
|
||||||
|
- chest_opens creato
|
||||||
|
- chest_open_items creati = cards_per_open
|
||||||
|
|
||||||
|
Caso B (saldo insufficiente):
|
||||||
|
- set wallet a 50 (o creare user con meno gold)
|
||||||
|
- open chest → 403
|
||||||
|
|
||||||
|
Caso C (idempotenza):
|
||||||
|
- inviare due volte la stessa request con stessa Idempotency-Key
|
||||||
|
- wallet deve scalare una volta sola
|
||||||
|
- response identica
|
||||||
|
|
||||||
|
Caso D (no duplicates):
|
||||||
|
- aprire fino a completare tutte le carte (o tutte della rarità)
|
||||||
|
- ulteriori aperture producono conversioni, senza violare vincoli DB
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 08 — Social: profilo pubblico + collezione altrui
|
||||||
|
### Obiettivo
|
||||||
|
Chiunque autenticato può vedere collezioni altrui (se pubbliche).
|
||||||
|
|
||||||
|
### Endpoint
|
||||||
|
- `GET /users/{nickname}`
|
||||||
|
- `GET /users/{nickname}/collection`
|
||||||
|
|
||||||
|
### Regole privacy
|
||||||
|
- se `is_collection_public=false` → 403 (o response “private” definita)
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: add public user profile and collection endpoints`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- Utente A apre carte
|
||||||
|
- Utente B fa GET su collezione A → vede lista
|
||||||
|
- Se A setta privacy false (TODO se implementare endpoint) → B riceve 403
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 09 — Test automatici backend (minimo indispensabile)
|
||||||
|
### Obiettivo
|
||||||
|
Test ripetibili per le feature core.
|
||||||
|
|
||||||
|
### Test richiesti
|
||||||
|
- register/login
|
||||||
|
- wallet iniziale
|
||||||
|
- open chest happy path
|
||||||
|
- open chest saldo insufficiente
|
||||||
|
- open chest idempotenza
|
||||||
|
- unique-only: non si possono inserire duplicati
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `test: add backend tests for core flows`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- `pytest` (o test runner equivalente) verde
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 10 — Client di test temporaneo (CLI o Postman)
|
||||||
|
### Obiettivo
|
||||||
|
Avere un modo semplice per fare E2E senza Unity.
|
||||||
|
|
||||||
|
### Opzione 1: CLI (consigliata)
|
||||||
|
- script che:
|
||||||
|
- register
|
||||||
|
- login
|
||||||
|
- open chest con Idempotency-Key
|
||||||
|
- stampa wallet e collection
|
||||||
|
- view other collection
|
||||||
|
|
||||||
|
### Opzione 2: Postman collection
|
||||||
|
- file esportato con env (base_url, tokens)
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `feat: add test client (cli/postman) for end-to-end runs`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- Eseguire scenario:
|
||||||
|
1) crea userA e userB
|
||||||
|
2) userA open chest 3 volte
|
||||||
|
3) userB legge collezione userA
|
||||||
|
4) verificare che non ci siano duplicati in userA
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 11 — Hardening minimo (prototipo, ma non fragile)
|
||||||
|
### Obiettivo
|
||||||
|
Ridurre bug e abusi evidenti.
|
||||||
|
|
||||||
|
### Azioni
|
||||||
|
- rate limit su login e open chest
|
||||||
|
- logging strutturato per chest_open
|
||||||
|
- gestione errori uniforme (JSON: code, message)
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
- `chore: add basic rate limiting and structured logs`
|
||||||
|
|
||||||
|
### Gate / Test
|
||||||
|
- aprire 20 volte in 1 secondo → deve limitare o rispondere coerentemente
|
||||||
|
- log contiene open_id e user_id
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4) Definition of Done (DoD) Prototipo
|
||||||
|
Il prototipo è “DONE” quando:
|
||||||
|
- [ ] docker compose up avvia stack
|
||||||
|
- [ ] register/login funzionano
|
||||||
|
- [ ] wallet non scende mai sotto zero
|
||||||
|
- [ ] open chest è transazionale e idempotente
|
||||||
|
- [ ] user_cards non contiene duplicati (vincolo DB)
|
||||||
|
- [ ] collezione pubblica di altri utenti è consultabile
|
||||||
|
- [ ] esistono test automatici minimi
|
||||||
|
- [ ] esiste client di test per E2E
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5) Prompt template per agente IA (uso consigliato)
|
||||||
|
## Prompt generale per ogni step
|
||||||
|
“In questo step implementa SOLO ciò che è richiesto, senza inventare funzionalità extra.
|
||||||
|
Rispetta i Gate/Test e aggiorna README se cambiano comandi.
|
||||||
|
Dopo ogni modifica, elenca i file creati/modificati.”
|
||||||
|
|
||||||
|
## Prompt per open chest (molto importante)
|
||||||
|
“Implementa `POST /chests/{chestId}/open` ESATTAMENTE secondo SOP.
|
||||||
|
Vincoli: transazione DB, idempotenza con Idempotency-Key, unique-only, conversione duplicati, audit.
|
||||||
|
Non cambiare comportamento e non introdurre logiche non esplicitate.”
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 6) Domande aperte (non procedere se non risolte)
|
||||||
|
- STACK_BACKEND = ?
|
||||||
|
- AUTH (refresh token sì/no) = ?
|
||||||
|
- CLIENT_TEST = ?
|
||||||
|
- Conversione duplicati: sempre 20 gold o dipende da rarità? (se dipende, definire tabella)
|
||||||
|
- Nickname: in register o endpoint separato? (definire)
|
||||||
13
backend/app/config.py
Normal file
13
backend/app/config.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
DB_HOST: str
|
||||||
|
DB_PORT: str = "5432"
|
||||||
|
DB_USER: str
|
||||||
|
DB_PASSWORD: str
|
||||||
|
DB_NAME: str
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
env_file = ".env"
|
||||||
|
|
||||||
|
settings = Settings()
|
||||||
17
backend/app/database.py
Normal file
17
backend/app/database.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker, declarative_base
|
||||||
|
from app.config import settings
|
||||||
|
|
||||||
|
SQLALCHEMY_DATABASE_URL = f"postgresql://{settings.DB_USER}:{settings.DB_PASSWORD}@{settings.DB_HOST}:{settings.DB_PORT}/{settings.DB_NAME}"
|
||||||
|
|
||||||
|
engine = create_engine(SQLALCHEMY_DATABASE_URL)
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
def get_db():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
@@ -1,7 +1,19 @@
|
|||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Depends, HTTPException
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy import text
|
||||||
|
from app.database import get_db
|
||||||
|
|
||||||
app = FastAPI(title="Card Game Backend")
|
app = FastAPI(title="Card Game Backend")
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
def health_check():
|
def health_check():
|
||||||
return {"status": "ok"}
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
@app.get("/db-check")
|
||||||
|
def db_check(db: Session = Depends(get_db)):
|
||||||
|
try:
|
||||||
|
# Execute simple query to check connection
|
||||||
|
db.execute(text("SELECT 1"))
|
||||||
|
return {"db": "ok"}
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail=f"Database connection failed: {str(e)}")
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ uvicorn
|
|||||||
sqlalchemy
|
sqlalchemy
|
||||||
psycopg2-binary
|
psycopg2-binary
|
||||||
asyncpg
|
asyncpg
|
||||||
|
pydantic-settings
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ services:
|
|||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
environment:
|
environment:
|
||||||
- DB_HOST=postgres
|
- DB_HOST=postgres
|
||||||
|
- DB_PORT=5432
|
||||||
- DB_USER=${POSTGRES_USER}
|
- DB_USER=${POSTGRES_USER}
|
||||||
- DB_PASS=${POSTGRES_PASSWORD}
|
- DB_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
- DB_NAME=${POSTGRES_DB}
|
- DB_NAME=${POSTGRES_DB}
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
|
|||||||
Reference in New Issue
Block a user