Files
kami_spider_monorepo/core/config.py
danial 0e41e7acce feat(core): 初始化核心配置和部署文件
- 添加 .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 全局异常处理中间件
2025-11-01 14:32:29 +08:00

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()