Bỏ qua

Backend Architecture

Backend sử dụng FastAPI với kiến trúc Layered Architecture — tách biệt rõ ràng giữa routing, business logic, data access, và validation.

Layered Architecture

graph TD
    A["🌐 API Layer<br/>api/courses.py"] --> B["💼 Service Layer<br/>services/"]
    B --> C["📋 Model Layer<br/>models/"]
    C --> D["🗄️ Database<br/>core/database.py"]
    A --> E["✅ Schema Layer<br/>schemas/"]
    A --> F["📦 Storage Service<br/>services/storage_service.py"]
Layer Thư mục Trách nhiệm
API api/ Route handlers, nhận request, trả response
Service services/ Business logic, xử lý nghiệp vụ
Model models/ SQLAlchemy ORM — định nghĩa bảng database
Schema schemas/ Pydantic — validate input/output
Core core/ Config, database connection
Utils utils/ Helper functions (slugify, etc.)

Entry Point — main.py

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from api.courses import router as courses_router
from core.config import settings

app = FastAPI(title="Cloudflare Courses API")

# CORS origins đọc từ biến môi trường
origins = [o.strip() for o in settings.CORS_ORIGINS.split(",")]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(courses_router)

CORS

CORS_ORIGINS là chuỗi phân cách bởi dấu phẩy. Ví dụ: http://localhost:3000,https://chienle.dev.

Configuration — core/config.py

Sử dụng Pydantic Settings để validate biến môi trường khi startup:

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    DATABASE_URL: str           # PostgreSQL connection string
    R2_ENDPOINT: str            # Cloudflare R2 endpoint
    R2_KEY: str                 # R2 Access Key
    R2_SECRET: str              # R2 Secret Key
    R2_BUCKET: str              # R2 Bucket name
    CDN_BASE: str               # Public CDN URL
    CORS_ORIGINS: str = "*"     # Allowed origins (mặc định: all)

    class Config:
        env_file = ".env"
        extra = "ignore"

Thiếu biến = Crash

Tất cả các biến (trừ CORS_ORIGINS) đều bắt buộc. Thiếu bất kỳ biến nào → Pydantic raise ValidationError → FastAPI crash ngay khi khởi động.

Database Connection — core/database.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base

engine = create_engine(
    settings.DATABASE_URL,
    pool_pre_ping=True,   # Auto-reconnect nếu connection bị drop
    pool_size=5,          # Connection pool size
    max_overflow=10       # Extra connections khi pool đầy
)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

def get_db():
    """Dependency injection — tạo DB session cho mỗi request."""
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

Thêm module mới

Khi cần thêm entity mới (ví dụ: User):

  1. Tạo model: models/user.py
  2. Tạo schema: schemas/user.py
  3. Tạo service: services/user_service.py
  4. Tạo router: api/users.py
  5. Register router trong main.py: app.include_router(users_router)
  6. Tạo migration: alembic revision --autogenerate -m "Add users table"
  7. Chạy migration: alembic upgrade head