beatmatchr/backend/config.py

119 lines
4.2 KiB
Python

"""Application configuration utilities."""
from __future__ import annotations
import os
from functools import lru_cache
from typing import Any, Dict
class Settings:
"""Configuration values loaded from environment variables.
The defaults are tuned for local development and match the docker-compose
configuration provided in this repository. Each value can be overridden by
setting the corresponding environment variable before starting the
application.
"""
def __init__(self) -> None:
self.postgres_user: str = os.getenv("POSTGRES_USER", "beatmatchr")
self.postgres_password: str = os.getenv("POSTGRES_PASSWORD", "beatmatchr")
self.postgres_db: str = os.getenv("POSTGRES_DB", "beatmatchr")
self.postgres_host: str = os.getenv("POSTGRES_HOST", "localhost")
self.postgres_port: int = int(os.getenv("POSTGRES_PORT", "5432"))
self.redis_host: str = os.getenv("REDIS_HOST", "localhost")
self.redis_port: int = int(os.getenv("REDIS_PORT", "6379"))
self.redis_db: int = int(os.getenv("REDIS_DB", "0"))
self.database_url: str = os.getenv(
"DATABASE_URL",
(
"postgresql+asyncpg://"
f"{self.postgres_user}:{self.postgres_password}"
f"@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}"
),
)
redis_base_url = f"redis://{self.redis_host}:{self.redis_port}/{self.redis_db}"
self.redis_url: str = os.getenv("REDIS_URL", redis_base_url)
self.celery_broker_url: str = os.getenv("CELERY_BROKER_URL", self.redis_url)
self.celery_result_backend: str = os.getenv(
"CELERY_RESULT_BACKEND", self.redis_url
)
def dict(self) -> Dict[str, Any]:
"""Return the settings as a plain dictionary (useful for debugging)."""
return {
"postgres_user": self.postgres_user,
"postgres_password": self.postgres_password,
"postgres_db": self.postgres_db,
"postgres_host": self.postgres_host,
"postgres_port": self.postgres_port,
"database_url": self.database_url,
"redis_host": self.redis_host,
"redis_port": self.redis_port,
"redis_db": self.redis_db,
"redis_url": self.redis_url,
"celery_broker_url": self.celery_broker_url,
"celery_result_backend": self.celery_result_backend,
}
from pathlib import Path
from typing import Optional
from pydantic import BaseSettings, Field
class Settings(BaseSettings):
"""Application configuration loaded from environment variables."""
database_url: str = Field(
default="sqlite+aiosqlite:///./beatmatchr.db",
description="SQLAlchemy database URL",
)
sync_database_url: Optional[str] = Field(
default="sqlite:///./beatmatchr.db",
description="Optional sync URL for background workers",
)
storage_base_path: Path = Field(
default=Path(os.getenv("BEATMATCHR_STORAGE", "./storage")),
description="Base path for file storage when using local filesystem backend.",
)
celery_broker_url: str = Field(
default=os.getenv("CELERY_BROKER_URL", "redis://localhost:6379/0"),
description="Broker URL for Celery workers.",
)
celery_result_backend: str = Field(
default=os.getenv("CELERY_RESULT_BACKEND", "redis://localhost:6379/0"),
description="Result backend URL for Celery workers.",
)
transcription_api_url: Optional[str] = Field(
default=os.getenv("TRANSCRIPTION_API_URL"),
description="External transcription service endpoint.",
)
transcription_api_key: Optional[str] = Field(
default=os.getenv("TRANSCRIPTION_API_KEY"),
description="API key for transcription service if required.",
)
class Config:
env_file = ".env"
env_file_encoding = "utf-8"
@lru_cache()
def get_settings() -> Settings:
"""Return a cached instance of :class:`Settings`."""
return Settings()
"""Return cached application settings instance."""
settings = Settings()
base_path = Path(settings.storage_base_path)
base_path.mkdir(parents=True, exist_ok=True)
return settings
settings = get_settings()