""" Управление SQLAlchemy движком и сессиями. """ from pathlib import Path from typing import AsyncGenerator from sqlalchemy.ext.asyncio import ( create_async_engine, async_sessionmaker, AsyncSession, AsyncEngine ) from configs import settings from middleware.loggers import logger from .models import Base __all__ = ("Database", "get_db") class Database: """ Менеджер SQLAlchemy базы данных. Attributes: engine: Async движок SQLAlchemy session_factory: Фабрика сессий """ def __init__(self, db_path: str = settings.DATABASE_PATH): """ Args: db_path: Путь к SQLite файлу """ # Создаём директорию если не существует db_file = Path(db_path) db_file.parent.mkdir(parents=True, exist_ok=True) # SQLite URL для async db_url = f"sqlite+aiosqlite:///{db_path}" # Создаём async движок self.engine: AsyncEngine = create_async_engine( db_url, echo=False, # Логирование SQL запросов (False для прода) future=True, pool_pre_ping=True, # Проверка соединения ) # Фабрика сессий self.session_factory = async_sessionmaker( self.engine, class_=AsyncSession, expire_on_commit=False, ) logger.info( f"SQLAlchemy инициализирован: {db_path}", log_type="DATABASE" ) async def init(self) -> None: """Создаёт все таблицы в БД""" try: async with self.engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) logger.info( "Таблицы базы данных созданы", log_type="DATABASE" ) except Exception as e: logger.error( f"Ошибка создания таблиц: {e}", log_type="DATABASE" ) raise async def close(self) -> None: """Закрывает соединения с БД""" await self.engine.dispose() logger.info("База данных закрыта", log_type="DATABASE") def get_session(self) -> AsyncGenerator[AsyncSession, None]: """ Создаёт новую сессию (контекстный менеджер). Usage: async with db.get_session() as session: result = await session.execute(select(BanWord)) words = result.scalars().all() Yields: AsyncSession: Сессия для работы с БД """ return self.session_factory() # Глобальный экземпляр _db_instance: Database | None = None def get_db(db_path: str = settings.DATABASE_PATH) -> Database: """ Возвращает глобальный экземпляр Database (Singleton). Args: db_path: Путь к БД (используется только при первом вызове) Returns: Database: Экземпляр базы данных """ global _db_instance if _db_instance is None: _db_instance = Database(db_path) return _db_instance