- "backend/models.py" - "alembic/versions/026_add_share_token.py" - "backend/pipeline/stages.py" - "backend/routers/shorts.py" - "backend/routers/shorts_public.py" - "backend/main.py" GSD-Task: S01/T01
115 lines
4.3 KiB
Python
115 lines
4.3 KiB
Python
"""Chrysopedia API — Knowledge extraction and retrieval system.
|
|
|
|
Entry point for the FastAPI application. Configures middleware,
|
|
structured logging, and mounts versioned API routers.
|
|
"""
|
|
|
|
import logging
|
|
import sys
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from config import get_settings
|
|
from routers import admin, auth, chat, consent, creator_chapters, creator_dashboard, creator_highlights, creators, files, follows, health, highlights, ingest, pipeline, posts, reports, search, shorts, shorts_public, stats, techniques, topics, videos
|
|
|
|
|
|
def _setup_logging() -> None:
|
|
"""Configure structured logging to stdout."""
|
|
settings = get_settings()
|
|
level = getattr(logging, settings.app_log_level.upper(), logging.INFO)
|
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setFormatter(
|
|
logging.Formatter(
|
|
fmt="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
|
|
datefmt="%Y-%m-%dT%H:%M:%S",
|
|
)
|
|
)
|
|
|
|
root = logging.getLogger()
|
|
root.setLevel(level)
|
|
# Avoid duplicate handlers on reload
|
|
root.handlers.clear()
|
|
root.addHandler(handler)
|
|
|
|
# Quiet noisy libraries
|
|
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
|
|
logging.getLogger("sqlalchemy.engine").setLevel(logging.WARNING)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI): # noqa: ARG001
|
|
"""Application lifespan: setup on startup, teardown on shutdown."""
|
|
_setup_logging()
|
|
logger = logging.getLogger("chrysopedia")
|
|
settings = get_settings()
|
|
logger.info(
|
|
"Chrysopedia API starting (env=%s, log_level=%s)",
|
|
settings.app_env,
|
|
settings.app_log_level,
|
|
)
|
|
# Ensure MinIO bucket exists (best-effort — API still starts if MinIO is down)
|
|
try:
|
|
from minio_client import ensure_bucket
|
|
ensure_bucket()
|
|
logger.info("MinIO bucket ready")
|
|
except Exception as exc:
|
|
logger.warning("MinIO bucket init failed (will retry on first upload): %s", exc)
|
|
yield
|
|
logger.info("Chrysopedia API shutting down")
|
|
|
|
|
|
app = FastAPI(
|
|
title="Chrysopedia API",
|
|
description="Knowledge extraction and retrieval for music production content",
|
|
version="0.1.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# ── Middleware ────────────────────────────────────────────────────────────────
|
|
|
|
settings = get_settings()
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# ── Routers ──────────────────────────────────────────────────────────────────
|
|
|
|
# Root-level health (no prefix)
|
|
app.include_router(health.router)
|
|
|
|
# Versioned API
|
|
app.include_router(admin.router, prefix="/api/v1")
|
|
app.include_router(auth.router, prefix="/api/v1")
|
|
app.include_router(chat.router, prefix="/api/v1")
|
|
app.include_router(consent.router, prefix="/api/v1")
|
|
app.include_router(creator_dashboard.router, prefix="/api/v1")
|
|
app.include_router(creator_chapters.router, prefix="/api/v1")
|
|
app.include_router(creator_highlights.router, prefix="/api/v1")
|
|
app.include_router(creators.router, prefix="/api/v1")
|
|
app.include_router(follows.router, prefix="/api/v1")
|
|
app.include_router(highlights.router, prefix="/api/v1")
|
|
app.include_router(ingest.router, prefix="/api/v1")
|
|
app.include_router(pipeline.router, prefix="/api/v1")
|
|
app.include_router(posts.router, prefix="/api/v1")
|
|
app.include_router(files.router, prefix="/api/v1")
|
|
app.include_router(reports.router, prefix="/api/v1")
|
|
app.include_router(search.router, prefix="/api/v1")
|
|
app.include_router(shorts.router, prefix="/api/v1")
|
|
app.include_router(shorts_public.router, prefix="/api/v1")
|
|
app.include_router(stats.router, prefix="/api/v1")
|
|
app.include_router(techniques.router, prefix="/api/v1")
|
|
app.include_router(topics.router, prefix="/api/v1")
|
|
app.include_router(videos.router, prefix="/api/v1")
|
|
|
|
|
|
@app.get("/api/v1/health")
|
|
async def api_health():
|
|
"""Lightweight version-prefixed health endpoint (no DB check)."""
|
|
return {"status": "ok", "version": "0.1.0"}
|