Initial commit: backend scaffold, auth, frontend login
- FastAPI + SQLAlchemy async + Alembic + Postgres backend - Auth: JWT access + rotating refresh tokens, argon2, roles, audit log - React 19 + Vite frontend: login page, protected route, auth context - Docker Compose: postgres, redis, migrate, api, worker (placeholder), frontend/nginx Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Проверки живости и готовности."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
import redis.asyncio as aioredis
|
||||
from fastapi import APIRouter, Response, status
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import text
|
||||
|
||||
from app.api.deps import SessionDep
|
||||
from app.core.config import settings
|
||||
from app.core.logging import get_logger
|
||||
|
||||
router = APIRouter(tags=["health"])
|
||||
log = get_logger(__name__)
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
status: Literal["ok", "degraded"]
|
||||
environment: str
|
||||
database: bool
|
||||
redis: bool
|
||||
|
||||
|
||||
@router.get("/health", response_model=HealthResponse)
|
||||
async def health() -> HealthResponse:
|
||||
"""Liveness: процесс жив. Внешние зависимости не проверяются.
|
||||
|
||||
Оркестратор не должен перезапускать контейнер из-за недоступного Postgres —
|
||||
перезапуск приложения проблему БД не решает.
|
||||
"""
|
||||
return HealthResponse(
|
||||
status="ok", environment=settings.environment, database=True, redis=True
|
||||
)
|
||||
|
||||
|
||||
@router.get("/health/ready", response_model=HealthResponse)
|
||||
async def readiness(session: SessionDep, response: Response) -> HealthResponse:
|
||||
"""Readiness: приложение способно обслуживать запросы."""
|
||||
db_ok = True
|
||||
redis_ok = True
|
||||
|
||||
try:
|
||||
await session.execute(text("SELECT 1"))
|
||||
except Exception as exc: # noqa: BLE001 — health-check не должен падать сам
|
||||
db_ok = False
|
||||
log.warning("readiness_db_failed", error=str(exc))
|
||||
|
||||
client = aioredis.from_url(settings.redis_url)
|
||||
try:
|
||||
await client.ping()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
redis_ok = False
|
||||
log.warning("readiness_redis_failed", error=str(exc))
|
||||
finally:
|
||||
await client.aclose()
|
||||
|
||||
healthy = db_ok and redis_ok
|
||||
if not healthy:
|
||||
response.status_code = status.HTTP_503_SERVICE_UNAVAILABLE
|
||||
|
||||
return HealthResponse(
|
||||
status="ok" if healthy else "degraded",
|
||||
environment=settings.environment,
|
||||
database=db_ok,
|
||||
redis=redis_ok,
|
||||
)
|
||||
Reference in New Issue
Block a user