import json from fastapi import APIRouter, Request, status from fastapi.responses import JSONResponse from core.api.publisher import IngestionQueueFull, KafkaPublishError from core.domain.errors import CDRProcessingError from core.domain.validation import parse_raw_cdr router = APIRouter() @router.post( "/cdr/raw", status_code=status.HTTP_202_ACCEPTED, ) async def ingest_raw_cdr(request: Request) -> JSONResponse: try: payload = await request.json() except (json.JSONDecodeError, UnicodeDecodeError) as exc: return JSONResponse( status_code=status.HTTP_400_BAD_REQUEST, content={ "error": "invalid_json", "detail": str(exc), }, ) if not isinstance(payload, dict): return JSONResponse( status_code=status.HTTP_400_BAD_REQUEST, content={ "error": "invalid_payload", "detail": "JSON payload must be an object.", }, ) try: raw_cdr = parse_raw_cdr(payload) except CDRProcessingError as exc: return JSONResponse( status_code=status.HTTP_400_BAD_REQUEST, content={ "error": exc.reason.value, "detail": exc.detail, "failed_field": exc.failed_field, }, ) try: await request.app.state.publisher.publish( payload, key=raw_cdr.raw_id, ) except IngestionQueueFull: return JSONResponse( status_code=status.HTTP_429_TOO_MANY_REQUESTS, content={ "error": "backpressure", "detail": "Ingestion queue is full.", }, ) except KafkaPublishError as exc: return JSONResponse( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, content={ "error": "kafka_unavailable", "detail": str(exc), }, ) return JSONResponse( status_code=status.HTTP_202_ACCEPTED, content={ "status": "accepted", "raw_id": raw_cdr.raw_id, }, )