codex / src /web /routes /external /registration.py
webhook's picture
Upload 137 files
89419ea verified
Raw History Blame Contribute Delete
5.01 kB
"""External registration batch routes."""
from __future__ import annotations
from typing import Any, Dict, Literal, Optional
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, status
from pydantic import BaseModel, ConfigDict, Field, model_validator
from ...deps.external_auth import require_external_api_key
router = APIRouter(dependencies=[Depends(require_external_api_key)])
class ExternalEmailSelection(BaseModel):
model_config = ConfigDict(extra="forbid")
type: str = Field(..., min_length=1)
service_id: Optional[int] = None
class ExternalUploadSelection(BaseModel):
model_config = ConfigDict(extra="forbid")
enabled: bool = False
provider: Optional[Literal["sub2api", "cpa", "tm"]] = None
service_id: Optional[int] = None
class ExternalExecutionOptions(BaseModel):
model_config = ConfigDict(extra="forbid")
mode: Literal["pipeline", "parallel"] = "pipeline"
concurrency: int = Field(default=1, ge=1, le=10000)
interval_min: int = Field(default=5, ge=0)
interval_max: int = Field(default=30, ge=0)
@model_validator(mode="after")
def validate_interval_bounds(self):
if self.interval_max < self.interval_min:
raise ValueError("interval_max must be greater than or equal to interval_min")
return self
class ExternalBatchCreateRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
count: int = Field(..., ge=1, le=10000000)
idempotency_key: Optional[str] = None
email: ExternalEmailSelection
upload: ExternalUploadSelection = Field(default_factory=ExternalUploadSelection)
execution: ExternalExecutionOptions = Field(default_factory=ExternalExecutionOptions)
@model_validator(mode="after")
def validate_upload(self):
if self.upload.enabled and not self.upload.provider:
raise ValueError("upload.provider is required when upload.enabled is true")
return self
def _create_external_batch(payload: Dict[str, Any], background_tasks: Optional[BackgroundTasks] = None) -> Dict[str, Any]:
try:
from ....core.external_batches.service import create_external_registration_batch # type: ignore
except Exception as exc: # pragma: no cover - handled by route
raise RuntimeError("external_batch_service_unavailable") from exc
return create_external_registration_batch(payload, background_tasks=background_tasks)
def _get_external_batch(batch_uuid: str) -> Dict[str, Any]:
try:
from ....core.external_batches.service import get_external_registration_batch_status # type: ignore
except Exception as exc: # pragma: no cover
raise RuntimeError("external_batch_service_unavailable") from exc
return get_external_registration_batch_status(batch_uuid)
def _cancel_external_batch(batch_uuid: str) -> Dict[str, Any]:
try:
from ....core.external_batches.service import cancel_external_registration_batch # type: ignore
except Exception as exc: # pragma: no cover
raise RuntimeError("external_batch_service_unavailable") from exc
return cancel_external_registration_batch(batch_uuid)
def _translate_error(exc: Exception) -> HTTPException:
detail = str(exc)
code = status.HTTP_404_NOT_FOUND if detail == "batch_not_found" else status.HTTP_400_BAD_REQUEST
return HTTPException(status_code=code, detail=detail)
@router.post("/batches", status_code=status.HTTP_202_ACCEPTED, summary="Create external registration batch")
def create_external_registration_batch(request: ExternalBatchCreateRequest, background_tasks: BackgroundTasks = None, response: Response = None) -> Dict[str, Any]:
try:
result = _create_external_batch(request.model_dump(), background_tasks=background_tasks)
if result.get("idempotent_replay") is True and response is not None:
response.status_code = status.HTTP_200_OK
return result
except ValueError as exc:
raise _translate_error(exc) from exc
except RuntimeError as exc:
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=str(exc)) from exc
@router.get("/batches/{batch_uuid}", summary="Get external registration batch status")
def get_external_registration_batch(batch_uuid: str) -> Dict[str, Any]:
try:
return _get_external_batch(batch_uuid)
except ValueError as exc:
raise _translate_error(exc) from exc
except RuntimeError as exc:
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=str(exc)) from exc
@router.post("/batches/{batch_uuid}/cancel", summary="Cancel external registration batch")
def cancel_external_registration_batch(batch_uuid: str) -> Dict[str, Any]:
try:
return _cancel_external_batch(batch_uuid)
except ValueError as exc:
raise _translate_error(exc) from exc
except RuntimeError as exc:
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=str(exc)) from exc