refactor: 第三方平台架构改造(Adapter Protocol + Gateway)

Phase 1: 异常体系统一
- 新增 PlatformError / PlatformErrorType 标准定义
- 改造所有 Provider 异常抛出为 PlatformError
- 注册全局 PlatformError exception handler

Phase 2: Adapter Protocol
- 新增 app/ai/adapters/base.py(PlatformAdapter + SyncCapable + TaskCapable + CallbackCapable)
- 新增 app/ai/adapters/constants.py(Method 常量)
- 新增 PlatformConfigLoader(config/platform-config.yaml)

Phase 3: HTTP Client 统一
- ViduProvider 从 aiohttp 迁移到 httpx(注入方式)
- VolcengineCaptionService 改为注入 http_client
- lifespan 统一管理所有 Client 创建和关闭

Phase 4: Gateway 骨架 + Adapter 实现
- 新增 ViduAdapter / VolcengineArkAdapter / VolcengineCaptionAdapter
- 新增 PlatformGateway(call_sync / submit_task / query_task / handle_webhook)
- 新增 LLMGateway(带 Fallback 降级链)
- lifespan 注册所有 Adapter 和 Gateway

Phase 6: 清理与验证
- 从 Settings 移除 VIDU_BASE_URL / VOLCENGINE_BASE_URL
- Provider 改为从 PlatformConfigLoader 读取 base_url
- 清理 volcengine_caption_service 全局单例
- config_loader 默认路径改为 platform-config.yaml
- Scheduler 注入共享 HTTP client
- vidu.py 回调路由使用 Adapter 验签和解析
- ruff 全量通过,应用启动测试通过
This commit is contained in:
小鱼开发
2026-05-04 16:07:16 +08:00
parent 0c921aca11
commit e58159fc42
34 changed files with 3688 additions and 1030 deletions
+79
View File
@@ -1,11 +1,22 @@
"""
自定义异常类
============
分层异常体系:
- AppException: 业务层错误(参数校验、权限、资源不存在等)
- PlatformError: 第三方平台调用错误(网络、限流、认证、服务异常等)
Router 层只处理这两类异常,其余全部兜底为 500。
"""
from fastapi import HTTPException, status
# ═══════════════════════════════════════════════════════════════
# 业务层异常(AppException 体系)
# ═══════════════════════════════════════════════════════════════
class AppException(HTTPException):
"""应用基础异常"""
@@ -87,3 +98,71 @@ class TaskFailedException(AppException):
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
message=message,
)
# ═══════════════════════════════════════════════════════════════
# 第三方平台异常(PlatformError 体系)
# ═══════════════════════════════════════════════════════════════
class PlatformErrorType:
"""第三方错误类型标准枚举
所有 Adapter 必须将供应商异常映射为以下标准类型之一,
确保前端和网关能够统一处理。
"""
RATE_LIMIT = "rate_limit" # 429,可重试
AUTH_FAILED = "auth_failed" # 401/403,不可重试
TIMEOUT = "timeout" # 连接/读取超时,可重试
SERVER_ERROR = "server_error" # 第三方 5xx,可重试
BAD_REQUEST = "bad_request" # 参数错误,不可重试
QUOTA_EXHAUSTED = "quota_exhausted" # 额度用完,不可重试(或延迟重试)
NOT_FOUND = "not_found" # 资源不存在,不可重试
UNKNOWN = "unknown" # 兜底
class PlatformError(Exception):
"""第三方平台调用失败的唯一异常类
Router 层只需 except PlatformError,即可返回标准 HTTP 状态码。
所有 app/services/ 和 app/ai/ 下的代码,对外抛出的异常必须是此类。
Example:
raise PlatformError(
"Vidu 限流",
platform="vidu",
retryable=True,
error_type=PlatformErrorType.RATE_LIMIT,
status_code=429,
)
"""
def __init__(
self,
message: str,
*,
platform: str,
retryable: bool = False,
error_type: str = PlatformErrorType.UNKNOWN,
status_code: int | None = None,
):
super().__init__(message)
self.platform = platform
self.retryable = retryable
self.error_type = error_type
self.status_code = status_code
def to_http_status(self) -> int:
"""根据 error_type 和 retryable 返回标准 HTTP 状态码"""
mapping = {
PlatformErrorType.RATE_LIMIT: 429,
PlatformErrorType.QUOTA_EXHAUSTED: 429,
PlatformErrorType.TIMEOUT: 504,
PlatformErrorType.AUTH_FAILED: 401,
PlatformErrorType.BAD_REQUEST: 400,
PlatformErrorType.NOT_FOUND: 404,
}
if self.error_type in mapping:
return mapping[self.error_type]
return 502 if self.retryable else 400