feat: Implement SQLAlchemy database layer with comprehensive models

Implemented a complete database layer for persistent storage of anime series,
episodes, download queue, and user sessions using SQLAlchemy ORM.

Features:
- 4 SQLAlchemy models: AnimeSeries, Episode, DownloadQueueItem, UserSession
- Automatic timestamp tracking via TimestampMixin
- Foreign key relationships with cascade deletes
- Async and sync database session support
- FastAPI dependency injection integration
- SQLite optimizations (WAL mode, foreign keys)
- Enum types for status and priority fields

Models:
- AnimeSeries: Series metadata with one-to-many relationships
- Episode: Individual episodes linked to series
- DownloadQueueItem: Queue persistence with progress tracking
- UserSession: JWT session storage with expiry and revocation

Database Management:
- Async engine creation with aiosqlite
- Session factory with proper lifecycle
- Connection pooling configuration
- Automatic table creation on initialization

Testing:
- 19 comprehensive unit tests (all passing)
- In-memory SQLite for test isolation
- Relationship and constraint validation
- Query operation testing

Documentation:
- Comprehensive database section in infrastructure.md
- Database package README with examples
- Implementation summary document
- Usage guides and troubleshooting

Dependencies:
- Added: sqlalchemy>=2.0.35 (Python 3.13 compatible)
- Added: alembic==1.13.0 (for future migrations)
- Added: aiosqlite>=0.19.0 (async SQLite driver)

Files:
- src/server/database/__init__.py (package exports)
- src/server/database/base.py (base classes and mixins)
- src/server/database/models.py (ORM models, ~435 lines)
- src/server/database/connection.py (connection management)
- src/server/database/migrations.py (migration placeholder)
- src/server/database/README.md (package documentation)
- tests/unit/test_database_models.py (19 test cases)
- DATABASE_IMPLEMENTATION_SUMMARY.md (implementation summary)

Closes #9 Database Layer implementation task
This commit is contained in:
2025-10-17 20:46:21 +02:00
parent 0d6cade56c
commit ff0d865b7c
12 changed files with 2390 additions and 49 deletions

View File

@@ -68,19 +68,34 @@ def reset_series_app() -> None:
_series_app = None
async def get_database_session() -> AsyncGenerator[Optional[object], None]:
async def get_database_session() -> AsyncGenerator:
"""
Dependency to get database session.
Yields:
AsyncSession: Database session for async operations
Example:
@app.get("/anime")
async def get_anime(db: AsyncSession = Depends(get_database_session)):
result = await db.execute(select(AnimeSeries))
return result.scalars().all()
"""
# TODO: Implement database session management
# This is a placeholder for future database implementation
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="Database functionality not yet implemented"
)
try:
from src.server.database import get_db_session
async with get_db_session() as session:
yield session
except ImportError:
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="Database functionality not installed"
)
except RuntimeError as e:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Database not available: {str(e)}"
)
def get_current_user(