main.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. from fastapi import FastAPI, HTTPException, Request
  2. from fastapi.responses import JSONResponse
  3. from fastapi.middleware.cors import CORSMiddleware
  4. from utils.params import DecodeContentParam, PatternContentParam
  5. from dotenv import load_dotenv, find_dotenv
  6. from typing import List, Dict, Any, Optional
  7. from tasks.decode import begin_decode_task
  8. from tasks.detail import get_decode_detail_by_task_id
  9. from tasks.pattern import begin_pattern_task
  10. from loguru import logger
  11. import sys
  12. logger.add(sink=sys.stderr, level="ERROR", backtrace=True, diagnose=True)
  13. # 响应消息映射
  14. RESPONSE_MSG_MAP = {
  15. 0: "success",
  16. 1002: "视频不存在",
  17. 2001: "解构/聚类任务创建失败",
  18. -1: "failed",
  19. 404: "任务不存在"
  20. }
  21. load_dotenv(find_dotenv(), override=False)
  22. app = FastAPI()
  23. app.add_middleware(
  24. CORSMiddleware,
  25. allow_origins=["*"],
  26. allow_credentials=True,
  27. allow_methods=["*"],
  28. allow_headers=["*"],
  29. )
  30. @app.exception_handler(HTTPException)
  31. async def http_exception_handler(request: Request, exc: HTTPException):
  32. """统一处理 HTTPException,保证返回结构与其它接口一致"""
  33. msg = RESPONSE_MSG_MAP.get(exc.status_code, "failed")
  34. content = {
  35. "code": exc.status_code,
  36. "msg": msg,
  37. "data": None,
  38. }
  39. # 将异常 detail 写入 reason,便于排查问题
  40. if exc.detail:
  41. content["reason"] = str(exc.detail)
  42. return JSONResponse(status_code=200, content=content)
  43. def _build_api_response(
  44. code: int,
  45. data: Any = None,
  46. reason: Optional[str] = None
  47. ) -> JSONResponse:
  48. """构建统一的API响应"""
  49. msg = RESPONSE_MSG_MAP.get(code, "failed")
  50. content = {
  51. "code": code,
  52. "msg": msg,
  53. "data": data
  54. }
  55. # 失败时添加 reason 字段
  56. if code != 0 and reason:
  57. content["reason"] = reason
  58. return JSONResponse(status_code=200, content=content)
  59. @app.post("/api/v1/content/tasks/decode")
  60. def decode_content(param: DecodeContentParam):
  61. """创建解构任务"""
  62. res = begin_decode_task(param)
  63. code = res.get("code", -1)
  64. task_id = res.get("task_id")
  65. reason = res.get("reason", "")
  66. return _build_api_response(
  67. code=code,
  68. data={"task_id": task_id} if task_id else None,
  69. reason=reason
  70. )
  71. @app.get("/api/v1/content/tasks/{taskId}")
  72. def get_task_detail(taskId: str):
  73. """获取任务详情"""
  74. result = get_decode_detail_by_task_id(taskId)
  75. # 任务不存在
  76. if result is None:
  77. return _build_api_response(code=404, data=None)
  78. # 直接返回结果(已经包含 code、msg、data、reason)
  79. return JSONResponse(status_code=200, content=result)
  80. @app.post("/api/v1/content/tasks/pattern")
  81. def pattern_content(param: PatternContentParam):
  82. """创建聚类任务"""
  83. res = begin_pattern_task(param)
  84. code = res.get("code", -1)
  85. task_id = res.get("task_id")
  86. reason = res.get("reason", "")
  87. return _build_api_response(
  88. code=code,
  89. data={"task_id": task_id} if task_id else None,
  90. reason=reason
  91. )