Files
virtual_board_member/app/core/database.py
Jonathan Pressnell 5b5714e4c2 feat: Complete Week 5 implementation - Agentic RAG & Multi-Agent Orchestration
- Implement Autonomous Workflow Engine with dynamic task decomposition
- Add Multi-Agent Communication Protocol with message routing
- Create Enhanced Reasoning Chains (CoT, ToT, Multi-Step, Parallel, Hybrid)
- Add comprehensive REST API endpoints for all Week 5 features
- Include 26/26 passing tests with full coverage
- Add complete documentation and API guides
- Update development plan to mark Week 5 as completed

Features:
- Dynamic task decomposition and parallel execution
- Agent registration, messaging, and coordination
- 5 reasoning methods with validation and learning
- Robust error handling and monitoring
- Multi-tenant support and security
- Production-ready architecture

Files added/modified:
- app/services/autonomous_workflow_engine.py
- app/services/agent_communication.py
- app/services/enhanced_reasoning.py
- app/api/v1/endpoints/week5_features.py
- tests/test_week5_features.py
- docs/week5_api_documentation.md
- docs/week5_readme.md
- WEEK5_COMPLETION_SUMMARY.md
- DEVELOPMENT_PLAN.md (updated)

All tests passing: 26/26
2025-08-10 09:25:46 -04:00

142 lines
3.9 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()
# Use lightweight SQLite during tests to avoid external dependencies
if settings.TESTING:
ASYNC_DB_URL = "sqlite+aiosqlite:///:memory:"
SYNC_DB_URL = "sqlite:///:memory:"
else:
ASYNC_DB_URL = settings.DATABASE_URL.replace("postgresql://", "postgresql+asyncpg://")
SYNC_DB_URL = settings.DATABASE_URL
# Create async engine
if settings.TESTING:
# SQLite configuration for testing
async_engine = create_async_engine(
ASYNC_DB_URL,
echo=settings.DEBUG,
connect_args={"check_same_thread": False},
)
else:
# PostgreSQL configuration for production
async_engine = create_async_engine(
ASYNC_DB_URL,
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
if settings.TESTING:
# SQLite configuration for testing
engine = create_engine(
SYNC_DB_URL,
echo=settings.DEBUG,
poolclass=StaticPool,
connect_args={"check_same_thread": False},
)
else:
# PostgreSQL configuration for production
engine = create_engine(
SYNC_DB_URL,
echo=settings.DEBUG,
)
# 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, tenant, 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:
if settings.TESTING:
# Simple no-op query for SQLite
await session.execute("SELECT 1")
else:
await session.execute("SELECT 1")
return True
except Exception as e:
logger.error("Database health check failed", error=str(e))
return False