from __future__ import annotations from functools import lru_cache from typing import List, Literal from pydantic import Field, field_validator from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore", ) APP_NAME: str = "reconciliation-report-service" VERSION: str = "1.0.0" ENV: Literal["development", "staging", "production"] = "production" DEBUG: bool = False HOST: str = "0.0.0.0" PORT: int = 7860 WORKERS: int = 4 ALLOWED_ORIGINS: List[str] = ["*"] API_KEY: str = Field(default="", description="Secret key required in X-API-Key header") SELF_PING_ENABLED: bool = True SELF_PING_URL: str = "https://validops-east-2-instance-2.hf.space/ping" SELF_PING_INTERVAL_SECONDS: int = 300 HF_TOKEN: str = Field( default="", description="Hugging Face Bearer token used exclusively for self-ping", ) MAX_FILE_SIZE_MB: int = 50 MAX_PAGES: int = 100 DEFAULT_DPI: int = 200 MAX_DPI: int = 600 DEFAULT_FORMAT: str = "PNG" DEFAULT_JPEG_QUALITY: int = 95 SUPPORTED_FORMATS: List[str] = ["PNG", "JPEG", "WEBP", "TIFF", "BMP"] PAGE_RENDER_WORKERS: int = 8 PDF_UPLOAD_MODE: Literal["per_page", "merged"] = "per_page" UPLOAD_CONCURRENCY: int = 4 FILE_SERVICE_TIMEOUT: float = 600.0 FILE_SERVICE_CONNECT_TIMEOUT: float = 100.0 OUTPUT_DIR: str = "/tmp/pdf2img_outputs" TEMP_DIR: str = "/tmp/pdf2img_temp" OUTPUT_TTL_SECONDS: int = 3600 LOG_LEVEL: str = "info" LOG_FORMAT: Literal["json", "console"] = "console" RATE_LIMIT: int = 100 RATE_LIMIT_WINDOW: int = 60 REDIS_URL: str = Field(default="", description="Redis connection URL for rate limiting") FILE_SERVICE_URL: str = Field(default="https://validops-east-3-instance-2.hf.space/api/v1/files/bulk-upload", description="External file upload service endpoint") FILE_SERVICE_API_KEY: str = Field(default="", description="API key for external file upload service") FILE_SERVICE_BEARER_TOKEN: str = Field(default="", description="Bearer token for external file upload service") @property def MAX_FILE_SIZE_BYTES(self) -> int: return self.MAX_FILE_SIZE_MB * 1024 * 1024 @property def rate_limit_redis_configured(self) -> bool: return bool(self.WORKERS > 1 and self.REDIS_URL) @field_validator("DEFAULT_FORMAT") @classmethod def normalise_format(cls, v: str) -> str: return v.upper() @lru_cache def get_settings() -> Settings: return Settings() settings = get_settings()