Files
virtual_board_member/app/core/database.py
Jonathan Pressnell 1a8ec37bed feat: Complete Week 2 - Document Processing Pipeline
- Implement multi-format document support (PDF, XLSX, CSV, PPTX, TXT, Images)
- Add S3-compatible storage service with tenant isolation
- Create document organization service with hierarchical folders and tagging
- Implement advanced document processing with table/chart extraction
- Add batch upload capabilities (up to 50 files)
- Create comprehensive document validation and security scanning
- Implement automatic metadata extraction and categorization
- Add document version control system
- Update DEVELOPMENT_PLAN.md to mark Week 2 as completed
- Add WEEK2_COMPLETION_SUMMARY.md with detailed implementation notes
- All tests passing (6/6) - 100% success rate
2025-08-08 15:47:43 -04:00

112 lines
3.0 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
engine = create_engine(
settings.DATABASE_URL,
echo=settings.DEBUG,
poolclass=StaticPool if settings.TESTING else None,
)
# Alias for compatibility
sync_engine = engine
# 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()
def get_db_sync():
"""Synchronous database session for non-async contexts."""
from sqlalchemy.orm import sessionmaker
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()
try:
yield db
finally:
db.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