Files
fastapi/app/api/health.py
T

57 lines
1.8 KiB
Python
Raw Normal View History

from fastapi import APIRouter
from fastapi.responses import JSONResponse
from sqlalchemy import text
from app.core.config import settings
from app.core.response import ok
from app.db.session import SessionLocal
router = APIRouter()
@router.get("/live")
def live():
"""存活检查:确认 FastAPI 进程已启动并可以响应请求。"""
return ok({"status": "live", "environment": settings.app_env})
@router.get("/ready")
def ready():
"""就绪检查:验证生产配置、MySQL 和 Redis 是否支持核心业务运行。"""
checks: dict[str, object] = {
"configuration": {"ok": True, "errors": []},
"mysql": {"ok": False},
"redis": {"ok": False},
}
config_errors = settings.deployment_config_errors()
checks["configuration"] = {"ok": not config_errors, "errors": config_errors}
try:
with SessionLocal() as db:
db.execute(text("SELECT 1"))
checks["mysql"] = {"ok": True}
except Exception:
checks["mysql"] = {"ok": False, "message": "database connection failed"}
try:
import redis
redis.Redis.from_url(
settings.redis_url,
decode_responses=True,
socket_connect_timeout=2,
socket_timeout=2,
).ping()
checks["redis"] = {"ok": True}
except Exception:
checks["redis"] = {"ok": False, "message": "redis connection failed"}
is_ready = all(bool(item.get("ok")) for item in checks.values() if isinstance(item, dict))
payload = {
"code": "OK" if is_ready else "SERVICE_NOT_READY",
"message": "success" if is_ready else "service dependencies are not ready",
"data": {"status": "ready" if is_ready else "not_ready", "checks": checks},
}
return JSONResponse(status_code=200 if is_ready else 503, content=payload)