""" MPR FastAPI Application Serves GraphQL API and Lambda callback endpoint. """ import os import sys from typing import Optional from uuid import UUID # Add project root to path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) from contextlib import asynccontextmanager from fastapi import FastAPI, Header, HTTPException from fastapi.middleware.cors import CORSMiddleware from strawberry.fastapi import GraphQLRouter from core.api.chunker_sse import router as chunker_router from core.api.detect_sse import router as detect_router from core.api.detect_replay import router as detect_replay_router from core.api.detect_config import router as detect_config_router from core.api.detect_sources import router as detect_sources_router from core.api.graphql import schema as graphql_schema CALLBACK_API_KEY = os.environ.get("CALLBACK_API_KEY", "") @asynccontextmanager async def lifespan(app): # Create/reset DB tables on startup from core.db.connection import create_tables create_tables() yield app = FastAPI( title="MPR API", description="Media Processor — GraphQL API", version="0.1.0", docs_url="/docs", redoc_url="/redoc", lifespan=lifespan, ) # CORS app.add_middleware( CORSMiddleware, allow_origins=["http://mpr.local.ar", "http://k8s.mpr.local.ar", "http://localhost:5173"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # GraphQL graphql_router = GraphQLRouter(schema=graphql_schema, graphql_ide="graphiql") app.include_router(graphql_router, prefix="/graphql") # Chunker SSE app.include_router(chunker_router) # Detection SSE app.include_router(detect_router) # Detection replay/retry app.include_router(detect_replay_router) # Detection config app.include_router(detect_config_router) # Detection sources + run launcher app.include_router(detect_sources_router) @app.get("/health") def health(): return {"status": "ok"} @app.get("/") def root(): """API root.""" return { "name": "MPR API", "version": "0.1.0", "graphql": "/graphql", } @app.post("/api/jobs/{job_id}/callback") def job_callback( job_id: UUID, payload: dict, x_api_key: Optional[str] = Header(None), ): """ Callback endpoint for Lambda to report job completion. Protected by API key. """ if CALLBACK_API_KEY and x_api_key != CALLBACK_API_KEY: raise HTTPException(status_code=403, detail="Invalid API key") from django.utils import timezone from core.db import get_job, update_job try: job = get_job(job_id) except Exception: raise HTTPException(status_code=404, detail="Job not found") status = payload.get("status", "failed") fields = { "status": status, "progress": 100.0 if status == "completed" else job.progress, } if payload.get("error"): fields["error_message"] = payload["error"] if status in ("completed", "failed"): fields["completed_at"] = timezone.now() update_job(job, **fields) return {"ok": True}