Phase 3 (Part 1): API Infrastructure - FastAPI, Database, Redis, gRPC Client
Completed Tasks (T027-T032): - ✅ FastAPI application with structured logging, CORS, global error handlers - ✅ Pydantic Settings for environment configuration - ✅ SQLAlchemy async engine with session management - ✅ Alembic migration environment setup - ✅ Redis async client with connection pooling - ✅ gRPC SDK Bridge client (placeholder - awaiting protobuf generation) Next: JWT utilities, middleware, database models 🤖 Generated with Claude Code
This commit is contained in:
69
src/api/models/__init__.py
Normal file
69
src/api/models/__init__.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
SQLAlchemy database setup with async support
|
||||
"""
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
from config import settings
|
||||
import structlog
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
# Create async engine
|
||||
engine = create_async_engine(
|
||||
settings.DATABASE_URL,
|
||||
echo=settings.ENVIRONMENT == "development",
|
||||
pool_size=settings.DATABASE_POOL_SIZE,
|
||||
max_overflow=settings.DATABASE_MAX_OVERFLOW,
|
||||
pool_pre_ping=True, # Verify connections before using
|
||||
)
|
||||
|
||||
# Create async session factory
|
||||
AsyncSessionLocal = async_sessionmaker(
|
||||
engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
)
|
||||
|
||||
# Base class for models
|
||||
class Base(DeclarativeBase):
|
||||
"""Base class for all database models"""
|
||||
pass
|
||||
|
||||
# Dependency for FastAPI routes
|
||||
async def get_db() -> AsyncSession:
|
||||
"""
|
||||
Dependency that provides database session to FastAPI routes
|
||||
Usage: db: AsyncSession = Depends(get_db)
|
||||
"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
try:
|
||||
yield session
|
||||
await session.commit()
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
raise
|
||||
finally:
|
||||
await session.close()
|
||||
|
||||
# Database initialization
|
||||
async def init_db():
|
||||
"""Initialize database connection (call on startup)"""
|
||||
try:
|
||||
logger.info("database_init", url=settings.DATABASE_URL.split("@")[-1]) # Hide credentials
|
||||
async with engine.begin() as conn:
|
||||
# Test connection
|
||||
await conn.run_sync(lambda _: None)
|
||||
logger.info("database_connected")
|
||||
except Exception as e:
|
||||
logger.error("database_connection_failed", error=str(e))
|
||||
raise
|
||||
|
||||
async def close_db():
|
||||
"""Close database connections (call on shutdown)"""
|
||||
try:
|
||||
logger.info("database_closing")
|
||||
await engine.dispose()
|
||||
logger.info("database_closed")
|
||||
except Exception as e:
|
||||
logger.error("database_close_failed", error=str(e))
|
||||
raise
|
||||
Reference in New Issue
Block a user