""" 数据库配置模块 使用pydantic进行配置验证和管理 """ import yaml import os from typing import Optional, List from pydantic_settings import BaseSettings from functools import lru_cache from pydantic import PostgresDsn, field_validator from pydantic_core.core_schema import FieldValidationInfo def load_yaml_config() -> dict: """从config.yaml加载配置""" config_path = os.path.join(os.path.dirname(__file__), "config.yaml") try: with open(config_path, 'r', encoding='utf-8') as f: return yaml.safe_load(f) or {} except (FileNotFoundError, yaml.YAMLError): return {} class Settings(BaseSettings): """应用配置类""" yaml_config: dict = load_yaml_config() RTSP_ENABLED: bool = yaml_config.get('rtsp_enabled', False) # API配置 API_V1_PREFIX: str = "/api/v1" PROJECT_NAME: str = "algorithm-service" PROJECT_VERSION: str = "1.0.0" PROJECT_DESCRIPTION: str = "algorithm-service" BACKEND_CORS_ORIGINS: List[str] = ["http://localhost:3000", "http://localhost:8000"] # 数据库配置 DATABASE_HOST: str = yaml_config.get('database', {}).get('host', "localhost") DATABASE_PORT: int = yaml_config.get('database', {}).get('port', 5432) DATABASE_USER: str = yaml_config.get('database', {}).get('user', "postgres") DATABASE_PASSWORD: str = yaml_config.get('database', {}).get('password', "yipai123") DATABASE_NAME: str = yaml_config.get('database', {}).get('name', "pmms") DATABASE_SCHEMA: str = yaml_config.get('database', {}).get('schema', "public") # 连接池配置 DATABASE_POOL_SIZE: int = yaml_config.get('database', {}).get('pool_size', 10) DATABASE_MAX_OVERFLOW: int = yaml_config.get('database', {}).get('max_overflow', 20) DATABASE_POOL_RECYCLE: int = yaml_config.get('database', {}).get('pool_recycle', 3600) # 连接回收时间(秒) DATABASE_ECHO: bool = yaml_config.get('database', {}).get('echo', False) # SQL日志,生产环境设为False # 应用配置 APP_NAME: str = "SurFaceFeature API" APP_VERSION: str = "1.0.0" DEBUG: bool = yaml_config.get('app', {}).get('debug', False) # 日志配置 LOG_LEVEL: str = yaml_config.get('app', {}).get('log_level', "INFO") LOG_FILE: Optional[str] = yaml_config.get('app', {}).get('log_file') # 异步配置 ASYNC_MODE: bool = False # 资源文件夹配置 FACE_REGISTER_IMAGE_RESOURCE_DIR: str = yaml_config.get('face', {}).get('face_register_image_dir', "D:/ruoyi/uploadPath/face") VIDEO_RESOURCE_DIR: str = yaml_config.get('face', {}).get('video_dir', "D:/ruoyi/uploadPath/video") FACE_CAL_FEATURE_TIMEOUT_HOURS: int = yaml_config.get('face', {}).get('face_cal_feature_timeout_hours', 10) FACE_MODEL_VERSION: int = yaml_config.get('face', {}).get('face_model_version', 0) #insight_face_buffalo_l FACE_USE_GPU: bool = yaml_config.get('face', {}).get('face_use_gpu', True) FACE_USE_NPU: bool = yaml_config.get('face', {}).get('face_use_npu', False) SUR_CONFIG_TYPE_FACE: int = yaml_config.get('face', {}).get('sur_config_type_face', 0) SUR_CONFIG_SCOPE_GLOBAL: int = yaml_config.get('face', {}).get('sur_config_scope_global', 0) # JWT配置(预留) SECRET_KEY: str = "your-secret-key-here-change-in-production" ALGORITHM: str = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES: int = 30 @property def DATABASE_URL(self) -> str: """构建数据库连接URL""" return f"postgresql://{self.DATABASE_USER}:{self.DATABASE_PASSWORD}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}" @property def ASYNC_DATABASE_URL(self) -> str: """构建异步数据库连接URL""" return f"postgresql+asyncpg://{self.DATABASE_USER}:{self.DATABASE_PASSWORD}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}" @field_validator("DATABASE_POOL_SIZE") def validate_pool_size(cls, v): """验证连接池大小""" if v < 1: raise ValueError("DATABASE_POOL_SIZE must be at least 1") if v > 100: raise ValueError("DATABASE_POOL_SIZE cannot exceed 100") return v class Config: env_file = ".env" env_file_encoding = "utf-8" case_sensitive = False extra = "ignore" @lru_cache() def get_settings() -> Settings: """ 获取配置单例 使用lru_cache避免重复加载.env文件 """ return Settings() # 导出配置实例 settings = get_settings()