Files
virtual_board_member/app/core/database.py
2025-08-07 16:11:14 -04:00

98 lines
2.7 KiB
Python

"""
Database configuration and connection setup for the Virtual Board Member AI System.
"""
import asyncio
from typing import AsyncGenerator
from sqlalchemy import create_engine, MetaData
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.pool import StaticPool
import structlog
from app.core.config import settings
logger = structlog.get_logger()
# Create async engine
async_engine = create_async_engine(
settings.DATABASE_URL.replace("postgresql://", "postgresql+asyncpg://"),
echo=settings.DEBUG,
pool_size=settings.DATABASE_POOL_SIZE,
max_overflow=settings.DATABASE_MAX_OVERFLOW,
pool_timeout=settings.DATABASE_POOL_TIMEOUT,
pool_pre_ping=True,
)
# Create sync engine for migrations
sync_engine = create_engine(
settings.DATABASE_URL,
echo=settings.DEBUG,
poolclass=StaticPool if settings.TESTING else None,
)
# Create session factory
AsyncSessionLocal = async_sessionmaker(
async_engine,
class_=AsyncSession,
expire_on_commit=False,
)
# Create base class for models
Base = declarative_base()
# Metadata for migrations
metadata = MetaData()
async def get_db() -> AsyncGenerator[AsyncSession, None]:
"""Dependency to get database session."""
async with AsyncSessionLocal() as session:
try:
yield session
except Exception as e:
await session.rollback()
logger.error("Database session error", error=str(e))
raise
finally:
await session.close()
async def init_db() -> None:
"""Initialize database tables."""
try:
async with async_engine.begin() as conn:
# Import all models to ensure they are registered
from app.models import user, document, commitment, audit_log # noqa
# Create all tables
await conn.run_sync(Base.metadata.create_all)
logger.info("Database tables created successfully")
except Exception as e:
logger.error("Failed to initialize database", error=str(e))
raise
async def close_db() -> None:
"""Close database connections."""
await async_engine.dispose()
logger.info("Database connections closed")
def get_sync_db():
"""Get synchronous database session for migrations."""
return sync_engine
# Database health check
async def check_db_health() -> bool:
"""Check database connectivity."""
try:
async with AsyncSessionLocal() as session:
await session.execute("SELECT 1")
return True
except Exception as e:
logger.error("Database health check failed", error=str(e))
return False