e58159fc42
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 全量通过,应用启动测试通过
115 lines
3.3 KiB
Python
115 lines
3.3 KiB
Python
"""
|
|
运行时配置管理
|
|
==============
|
|
|
|
支持热重载的运行时配置,轮询检查文件 mtime(10秒间隔)
|
|
+ Admin API 手动触发 reload。
|
|
|
|
配置来源:config/platform-config.yaml 中的 runtime section
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
try:
|
|
import yaml
|
|
|
|
YAML_AVAILABLE = True
|
|
except ImportError:
|
|
YAML_AVAILABLE = False
|
|
logger.warning("PyYAML 未安装")
|
|
|
|
|
|
class RuntimeConfig:
|
|
"""运行时配置管理器
|
|
|
|
从 platform-config.yaml 的 runtime section 加载配置,
|
|
支持自动热重载(轮询检查 mtime)和手动强制重载。
|
|
"""
|
|
|
|
DEFAULT_CONFIG_PATH = (
|
|
Path(__file__).parent.parent.parent / "config" / "platform-config.yaml"
|
|
)
|
|
DEFAULT_POLL_INTERVAL = 10 # 秒
|
|
|
|
def __init__(self, config_path: str | None = None):
|
|
self.config_path = Path(config_path) if config_path else self.DEFAULT_CONFIG_PATH
|
|
self._config: dict[str, Any] = {}
|
|
self._last_modified: float = 0
|
|
self._version: str = ""
|
|
self._load()
|
|
|
|
def _load(self) -> bool:
|
|
"""加载配置文件中的 runtime section"""
|
|
if not self.config_path.exists():
|
|
logger.warning(f"配置文件不存在: {self.config_path}")
|
|
return False
|
|
|
|
try:
|
|
with open(self.config_path, encoding="utf-8") as f:
|
|
if YAML_AVAILABLE:
|
|
config = yaml.safe_load(f)
|
|
else:
|
|
import json
|
|
|
|
config = json.load(f)
|
|
|
|
self._config = config.get("runtime", {})
|
|
self._last_modified = self.config_path.stat().st_mtime
|
|
self._version = config.get("version", "")
|
|
logger.info(
|
|
f"Runtime config loaded: {len(self._config)} sections, "
|
|
f"version={self._version or 'none'}"
|
|
)
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Runtime config load failed: {e}")
|
|
return False
|
|
|
|
async def _reload_if_changed(self) -> bool:
|
|
"""检查文件是否更新,如有则重载"""
|
|
try:
|
|
mtime = os.path.getmtime(self.config_path)
|
|
if mtime > self._last_modified:
|
|
logger.info(f"Runtime config changed, reloading: {self.config_path}")
|
|
return self._load()
|
|
except Exception as e:
|
|
logger.warning(f"Runtime config reload check failed: {e}")
|
|
return False
|
|
|
|
async def get(self, key: str, default: Any = None) -> Any:
|
|
"""获取配置项,自动检查是否需要重载"""
|
|
await self._reload_if_changed()
|
|
return self._config.get(key, default)
|
|
|
|
async def force_reload(self) -> bool:
|
|
"""Admin API 调用:手动强制重载"""
|
|
return self._load()
|
|
|
|
@property
|
|
def version(self) -> str:
|
|
return self._version
|
|
|
|
def get_raw(self) -> dict[str, Any]:
|
|
"""获取原始配置(用于 Admin API 展示)"""
|
|
return self._config.copy()
|
|
|
|
|
|
# 全局运行时配置实例
|
|
_runtime_config: RuntimeConfig | None = None
|
|
|
|
|
|
def get_runtime_config() -> RuntimeConfig:
|
|
"""获取全局运行时配置单例"""
|
|
global _runtime_config
|
|
if _runtime_config is None:
|
|
_runtime_config = RuntimeConfig()
|
|
return _runtime_config
|