decode.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. """Formal decode API routes."""
  2. from __future__ import annotations
  3. from typing import Any
  4. from uuid import UUID
  5. from fastapi import APIRouter, Depends, HTTPException
  6. from app.dependencies import get_acquisition_repository, get_decode_repository
  7. from app.schemas import (
  8. CandidateItemSchema,
  9. DecodeResultSchema,
  10. IngestRecordSchema,
  11. KnowledgeParticleSchema,
  12. MediaAssetSchema,
  13. PayloadDraftSchema,
  14. ScopeResultSchema,
  15. )
  16. router = APIRouter(prefix="/api/decode", tags=["decode"])
  17. @router.get("/items/{item_id}/result", response_model=DecodeResultSchema)
  18. def decode_result(
  19. item_id: UUID,
  20. repo: Any = Depends(get_decode_repository),
  21. ) -> DecodeResultSchema:
  22. getter = getattr(repo, "get_decode_result_for_item", None)
  23. if getter is None:
  24. raise HTTPException(status_code=501, detail="decode result reader is not implemented")
  25. return DecodeResultSchema.model_validate(getter(item_id))
  26. @router.get("/items/{item_id}/detail")
  27. def decode_item_detail(
  28. item_id: UUID,
  29. acquisition_repo: Any = Depends(get_acquisition_repository),
  30. decode_repo: Any = Depends(get_decode_repository),
  31. ) -> dict[str, Any]:
  32. try:
  33. item = acquisition_repo.get_candidate_item(item_id)
  34. media = acquisition_repo.list_media_assets_for_item(item_id)
  35. except Exception as exc:
  36. raise HTTPException(status_code=404, detail=f"candidate item not found: {exc}") from exc
  37. try:
  38. result = decode_repo.get_decode_result_for_item(item_id)
  39. except Exception as exc:
  40. result = None
  41. list_particles = getattr(decode_repo, "list_knowledge_particles", None)
  42. list_scopes = getattr(decode_repo, "list_scope_results", None)
  43. list_payloads = getattr(decode_repo, "list_payload_drafts", None)
  44. list_ingests = getattr(decode_repo, "list_ingest_records", None)
  45. raw_item = item.model_dump() if hasattr(item, "model_dump") else dict(item)
  46. item_payload = CandidateItemSchema.model_validate(
  47. {
  48. **raw_item,
  49. "media_assets": [
  50. MediaAssetSchema.model_validate(row).model_dump(mode="json")
  51. for row in media
  52. ],
  53. }
  54. ).model_dump(mode="json")
  55. return {
  56. "item": item_payload,
  57. "decode_result": (
  58. DecodeResultSchema.model_validate(result).model_dump(mode="json")
  59. if result is not None
  60. else None
  61. ),
  62. "knowledge_particles": [
  63. KnowledgeParticleSchema.model_validate(row).model_dump(mode="json")
  64. for row in (list_particles(item_id=item_id) if list_particles else [])
  65. ],
  66. "scope_results": [
  67. ScopeResultSchema.model_validate(row).model_dump(mode="json")
  68. for row in (list_scopes(item_id=item_id) if list_scopes else [])
  69. ],
  70. "payload_drafts": [
  71. PayloadDraftSchema.model_validate(row).model_dump(mode="json")
  72. for row in (list_payloads(item_id=item_id) if list_payloads else [])
  73. ],
  74. "ingest_records": [
  75. IngestRecordSchema.model_validate(row).model_dump(mode="json")
  76. for row in (list_ingests(item_id=item_id) if list_ingests else [])
  77. ],
  78. }
  79. @router.post("/items/{item_id}/jobs")
  80. def enqueue_decode_job(
  81. item_id: UUID,
  82. repo: Any = Depends(get_decode_repository),
  83. ) -> dict[str, Any]:
  84. create = getattr(repo, "create_decode_job", None)
  85. if create is None:
  86. raise HTTPException(status_code=501, detail="decode job writer is not implemented")
  87. job = create(item_id=item_id, status="pending")
  88. return {"job": job.model_dump(mode="json") if hasattr(job, "model_dump") else job}