107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
import os
|
||
from dataclasses import dataclass, field
|
||
from pathlib import Path
|
||
|
||
from dotenv import load_dotenv
|
||
|
||
load_dotenv()
|
||
|
||
|
||
TRUE_VALUES = {"1", "true", "yes", "on"}
|
||
|
||
|
||
# Хелперы для чтения env-переменных с приведением типов
|
||
|
||
def _env_str(name: str, default: str) -> str:
|
||
value = os.getenv(name)
|
||
return value if value is not None else default
|
||
|
||
|
||
def _env_optional_str(name: str) -> str | None:
|
||
value = os.getenv(name)
|
||
if value is None:
|
||
return None
|
||
value = value.strip()
|
||
return value or None
|
||
|
||
|
||
def _env_path_str(name: str) -> str | None:
|
||
value = _env_optional_str(name)
|
||
if value is None:
|
||
return None
|
||
return str(Path(value).expanduser())
|
||
|
||
|
||
def _env_bool(name: str, default: bool) -> bool:
|
||
fallback = "true" if default else "false"
|
||
return _env_str(name, fallback).strip().lower() in TRUE_VALUES
|
||
|
||
|
||
def _env_int(name: str, default: int) -> int:
|
||
return int(_env_str(name, str(default)).strip())
|
||
|
||
|
||
def _env_float(name: str, default: float) -> float:
|
||
return float(_env_str(name, str(default)).strip())
|
||
|
||
|
||
# Конфиг браузерного отпечатка (User-Agent для HTTP запросов)
|
||
|
||
@dataclass(slots=True)
|
||
class FingerprintConfig:
|
||
user_agent: str = (
|
||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||
"Chrome/135.0.0.0 Safari/537.36"
|
||
)
|
||
|
||
|
||
# - Конфиг PostgreSQL (URL, пул соединений, pool_recycle)
|
||
|
||
@dataclass(slots=True)
|
||
class DatabaseConfig:
|
||
url: str = _env_str("ENCAR_DATABASE_URL", "postgresql+psycopg2://encar:encar@localhost:5434/encar_db")
|
||
echo: bool = _env_bool("ENCAR_DATABASE_ECHO", False)
|
||
pool_size: int = _env_int("ENCAR_DATABASE_POOL_SIZE", 5)
|
||
max_overflow: int = _env_int("ENCAR_DATABASE_MAX_OVERFLOW", 10)
|
||
pool_recycle_seconds: int = _env_int("ENCAR_DATABASE_POOL_RECYCLE_SECONDS", 1800)
|
||
auto_create_tables: bool = _env_bool("ENCAR_DATABASE_AUTO_CREATE_TABLES", False)
|
||
|
||
|
||
# --- Конфиг Redis (URL для Celery broker) ---
|
||
|
||
@dataclass(slots=True)
|
||
class RedisConfig:
|
||
url: str = _env_str("ENCAR_REDIS_URL", "redis://localhost:6380/1")
|
||
|
||
|
||
# --- Конфиг Celery (лимиты задач, concurrency, beat-расписание) ---
|
||
|
||
@dataclass(slots=True)
|
||
class CeleryConfig:
|
||
broker_url: str = _env_str("CELERY_BROKER_URL", "")
|
||
result_backend: str = _env_str("CELERY_RESULT_BACKEND", "")
|
||
task_soft_time_limit: int = _env_int("CELERY_TASK_SOFT_TIME_LIMIT", 14400)
|
||
task_time_limit: int = _env_int("CELERY_TASK_TIME_LIMIT", 14520)
|
||
worker_concurrency: int = _env_int("CELERY_WORKER_CONCURRENCY", 4)
|
||
worker_max_tasks_per_child: int = _env_int("CELERY_WORKER_MAX_TASKS_PER_CHILD", 50)
|
||
broker_visibility_timeout: int = _env_int("CELERY_BROKER_VISIBILITY_TIMEOUT", 7200)
|
||
# Encar settings
|
||
encar_beat_interval_minutes: int = _env_int("ENCAR_BEAT_INTERVAL_MINUTES", 60)
|
||
encar_beat_limit: int | None = _env_int("ENCAR_BEAT_LIMIT", 0) or None
|
||
|
||
|
||
# --- Главный объект настроек: собирает все блоки конфигурации ---
|
||
|
||
@dataclass(slots=True)
|
||
class Settings:
|
||
log_level: str = _env_str("ENCAR_LOG_LEVEL", "INFO")
|
||
log_file: str | None = _env_optional_str("ENCAR_LOG_FILE")
|
||
fingerprint: FingerprintConfig = field(default_factory=FingerprintConfig)
|
||
database: DatabaseConfig = field(default_factory=DatabaseConfig)
|
||
redis: RedisConfig = field(default_factory=RedisConfig)
|
||
celery: CeleryConfig = field(default_factory=CeleryConfig)
|
||
|
||
# Глобальный синглтон — используется по умолчанию во всех модулях.
|
||
settings = Settings()
|