Files
telecom-cdr-pipeline/src/core/api/routes.py

84 lines
2.1 KiB
Python

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,
},
)