3e1fcd69b5
- backend/db/models.py: 11 SQLAlchemy 2.0 ORM models (User, Quota, RefreshToken,
Folder, Document, Topic, DocumentTopic, Share, AuditLog, CloudConnection, Group)
- Document.user_id declared nullable=True per D-03 (Phase 2 adds NOT NULL)
- AuditLog.metadata_ uses mapped_column("metadata", JSONB) to avoid DeclarativeBase
reserved-attribute conflict
- Group table stub for D-02 (v2 feature, seeded per PROJECT.md)
- Uses Optional[X] instead of X | None for Python < 3.10 compatibility
- backend/db/session.py: async engine (pool_pre_ping=True, expire_on_commit=False)
- backend/deps/db.py: async get_db() FastAPI dependency yielding AsyncSession
27 lines
937 B
Python
27 lines
937 B
Python
"""
|
|
Async SQLAlchemy engine and session factory for DocuVault.
|
|
|
|
The engine reads DATABASE_URL (restricted docuvault_app user — DML only).
|
|
The Alembic migration runner uses DATABASE_MIGRATE_URL (DDL user) separately.
|
|
|
|
Key settings:
|
|
pool_pre_ping=True — detect stale connections before use
|
|
expire_on_commit=False — prevent MissingGreenlet errors after commit in
|
|
async context (RESEARCH.md Pitfall 1)
|
|
"""
|
|
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
|
|
|
|
from config import settings
|
|
|
|
engine = create_async_engine(
|
|
settings.database_url, # postgresql+psycopg://docuvault_app:...@postgres/docuvault
|
|
pool_pre_ping=True, # detect stale connections before use
|
|
echo=False,
|
|
)
|
|
|
|
AsyncSessionLocal = async_sessionmaker(
|
|
engine,
|
|
class_=AsyncSession,
|
|
expire_on_commit=False, # prevent MissingGreenlet errors after commit (Pitfall 1)
|
|
)
|