- 添加 .env.example 环境变量配置示例 - 添加 .gitignore 忽略文件配置 - 添加 core/config.py 配置管理模块 - 添加 deployments/k8s/configmap.yaml Kubernetes 配置 - 添加 core/database.py 数据库连接管理模块 - 添加 core/dependencies.py 全局依赖模块 - 添加 DEPENDENCIES_UPDATED.md 依赖更新记录 - 添加 deployments/k8s/deployment.yaml Kubernetes 部署配置- 添加 deployments/swarm/docker-compose.swarm.yml Docker Swarm 部署配置 - 添加 deployments/docker/docker-compose.yml Docker 部署配置 - 添加 deployments/docker/Dockerfile 应用镜像构建文件 - 添加 middleware/error_handler.py 全局异常处理中间件
146 lines
5.7 KiB
Python
146 lines
5.7 KiB
Python
"""
|
|
Core configuration management using Pydantic Settings.
|
|
All configuration loaded from environment variables with validation.
|
|
"""
|
|
|
|
from typing import Literal
|
|
from pydantic import Field, field_validator
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""
|
|
Application settings with environment variable support.
|
|
|
|
Configuration is loaded from environment variables and .env files.
|
|
All settings are validated at startup using Pydantic validators.
|
|
"""
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=False,
|
|
extra="ignore",
|
|
)
|
|
|
|
# Application Settings
|
|
app_name: str = Field(default="kami_spider", description="Application name")
|
|
environment: Literal["development", "staging", "production"] = Field(
|
|
default="development",
|
|
description="Runtime environment"
|
|
)
|
|
debug: bool = Field(default=False, description="Debug mode")
|
|
host: str = Field(default="0.0.0.0", description="Server host")
|
|
port: int = Field(default=8000, description="Server port")
|
|
workers: int = Field(default=1, description="Number of worker processes")
|
|
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = Field(
|
|
default="INFO",
|
|
description="Logging level"
|
|
)
|
|
|
|
# Database Settings
|
|
db_host: str = Field(default="localhost", description="MySQL host")
|
|
db_port: int = Field(default=3306, description="MySQL port")
|
|
db_name: str = Field(default="kami_spider", description="Database name")
|
|
db_user: str = Field(default="root", description="Database user")
|
|
db_password: str = Field(default="", description="Database password")
|
|
db_pool_size: int = Field(default=10, description="Database connection pool size")
|
|
db_max_overflow: int = Field(default=20, description="Database max overflow connections")
|
|
db_pool_recycle: int = Field(default=3600, description="Database pool recycle time in seconds")
|
|
db_pool_pre_ping: bool = Field(default=True, description="Test connections before using")
|
|
db_echo: bool = Field(default=False, description="Echo SQL statements")
|
|
|
|
# Redis Settings
|
|
redis_host: str = Field(default="localhost", description="Redis host")
|
|
redis_port: int = Field(default=6379, description="Redis port")
|
|
redis_db: int = Field(default=0, description="Redis database number")
|
|
redis_password: str = Field(default="", description="Redis password")
|
|
redis_max_connections: int = Field(default=50, description="Redis connection pool max connections")
|
|
redis_decode_responses: bool = Field(default=True, description="Decode Redis responses to strings")
|
|
|
|
# OpenTelemetry Settings
|
|
otel_enabled: bool = Field(default=True, description="Enable OpenTelemetry")
|
|
otel_service_name: str = Field(default="kami_spider", description="Service name for traces")
|
|
otel_exporter_endpoint: str = Field(
|
|
default="38.38.251.113:31547",
|
|
description="OpenTelemetry collector gRPC endpoint"
|
|
)
|
|
otel_exporter_insecure: bool = Field(default=True, description="Use insecure gRPC connection")
|
|
otel_sample_rate: float = Field(default=1.0, description="Trace sampling rate (0.0 to 1.0)")
|
|
|
|
# CORS Settings
|
|
cors_enabled: bool = Field(default=True, description="Enable CORS")
|
|
cors_allow_origins: list[str] = Field(
|
|
default=["*"],
|
|
description="Allowed CORS origins"
|
|
)
|
|
cors_allow_credentials: bool = Field(default=True, description="Allow credentials in CORS")
|
|
cors_allow_methods: list[str] = Field(
|
|
default=["*"],
|
|
description="Allowed HTTP methods"
|
|
)
|
|
cors_allow_headers: list[str] = Field(
|
|
default=["*"],
|
|
description="Allowed HTTP headers"
|
|
)
|
|
|
|
# Security Settings
|
|
secret_key: str = Field(
|
|
default="change-me-in-production",
|
|
description="Secret key for signing tokens"
|
|
)
|
|
|
|
@field_validator("workers")
|
|
@classmethod
|
|
def validate_workers(cls, v: int) -> int:
|
|
"""Ensure workers is at least 1."""
|
|
if v < 1:
|
|
raise ValueError("workers must be at least 1")
|
|
return v
|
|
|
|
@field_validator("otel_sample_rate")
|
|
@classmethod
|
|
def validate_sample_rate(cls, v: float) -> float:
|
|
"""Ensure sample rate is between 0.0 and 1.0."""
|
|
if not 0.0 <= v <= 1.0:
|
|
raise ValueError("otel_sample_rate must be between 0.0 and 1.0")
|
|
return v
|
|
|
|
@property
|
|
def database_url(self) -> str:
|
|
"""Generate async database URL for SQLModel/SQLAlchemy."""
|
|
password_part = f":{self.db_password}" if self.db_password else ""
|
|
return (
|
|
f"mysql+aiomysql://{self.db_user}{password_part}"
|
|
f"@{self.db_host}:{self.db_port}/{self.db_name}"
|
|
)
|
|
|
|
@property
|
|
def sync_database_url(self) -> str:
|
|
"""Generate sync database URL for Alembic migrations."""
|
|
password_part = f":{self.db_password}" if self.db_password else ""
|
|
return (
|
|
f"mysql+pymysql://{self.db_user}{password_part}"
|
|
f"@{self.db_host}:{self.db_port}/{self.db_name}"
|
|
)
|
|
|
|
@property
|
|
def redis_url(self) -> str:
|
|
"""Generate Redis URL."""
|
|
password_part = f":{self.redis_password}@" if self.redis_password else ""
|
|
return f"redis://{password_part}{self.redis_host}:{self.redis_port}/{self.redis_db}"
|
|
|
|
@property
|
|
def is_production(self) -> bool:
|
|
"""Check if running in production environment."""
|
|
return self.environment == "production"
|
|
|
|
@property
|
|
def is_development(self) -> bool:
|
|
"""Check if running in development environment."""
|
|
return self.environment == "development"
|
|
|
|
|
|
# Global settings instance
|
|
settings = Settings()
|