Implemented database service layer with CRUD operations for all models: - AnimeSeriesService: Create, read, update, delete, search anime series - EpisodeService: Episode management and download tracking - DownloadQueueService: Priority-based queue with status tracking - UserSessionService: Session management with JWT support Features: - Repository pattern for clean separation of concerns - Full async/await support for non-blocking operations - Comprehensive type hints and docstrings - Transaction management via FastAPI dependency injection - Priority queue ordering (HIGH > NORMAL > LOW) - Automatic timestamp management - Cascade delete support Testing: - 22 comprehensive unit tests with 100% pass rate - In-memory SQLite for isolated testing - All CRUD operations tested Documentation: - Enhanced database README with service examples - Integration examples in examples.py - Updated infrastructure.md with service details - Migration utilities for schema management Files: - src/server/database/service.py (968 lines) - src/server/database/examples.py (467 lines) - tests/unit/test_database_service.py (22 tests) - src/server/database/migrations.py (enhanced) - src/server/database/__init__.py (exports added) Closes #9 - Database Layer: Create database service
168 lines
4.7 KiB
Python
168 lines
4.7 KiB
Python
"""Database migration utilities.
|
|
|
|
This module provides utilities for database migrations and schema versioning.
|
|
Alembic integration can be added when needed for production environments.
|
|
|
|
For now, we use SQLAlchemy's create_all for automatic schema creation.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Optional
|
|
|
|
from sqlalchemy import text
|
|
from sqlalchemy.ext.asyncio import AsyncEngine
|
|
|
|
from src.server.database.base import Base
|
|
from src.server.database.connection import get_engine, get_sync_engine
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def initialize_schema(engine: Optional[AsyncEngine] = None) -> None:
|
|
"""Initialize database schema.
|
|
|
|
Creates all tables defined in Base metadata if they don't exist.
|
|
This is a simple migration strategy suitable for single-instance deployments.
|
|
|
|
For production with multiple instances, consider using Alembic:
|
|
- alembic init alembic
|
|
- alembic revision --autogenerate -m "Initial schema"
|
|
- alembic upgrade head
|
|
|
|
Args:
|
|
engine: Optional database engine (uses default if not provided)
|
|
|
|
Raises:
|
|
RuntimeError: If database is not initialized
|
|
"""
|
|
if engine is None:
|
|
engine = get_engine()
|
|
|
|
logger.info("Initializing database schema...")
|
|
|
|
# Create all tables
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
|
|
logger.info("Database schema initialized successfully")
|
|
|
|
|
|
async def check_schema_version(engine: Optional[AsyncEngine] = None) -> str:
|
|
"""Check current database schema version.
|
|
|
|
Returns a simple version identifier based on existing tables.
|
|
For production, consider using Alembic for proper versioning.
|
|
|
|
Args:
|
|
engine: Optional database engine (uses default if not provided)
|
|
|
|
Returns:
|
|
Schema version string
|
|
|
|
Raises:
|
|
RuntimeError: If database is not initialized
|
|
"""
|
|
if engine is None:
|
|
engine = get_engine()
|
|
|
|
async with engine.connect() as conn:
|
|
# Check which tables exist
|
|
result = await conn.execute(
|
|
text(
|
|
"SELECT name FROM sqlite_master "
|
|
"WHERE type='table' AND name NOT LIKE 'sqlite_%'"
|
|
)
|
|
)
|
|
tables = [row[0] for row in result]
|
|
|
|
if not tables:
|
|
return "empty"
|
|
elif len(tables) == 4 and all(
|
|
t in tables for t in [
|
|
"anime_series",
|
|
"episodes",
|
|
"download_queue",
|
|
"user_sessions",
|
|
]
|
|
):
|
|
return "v1.0"
|
|
else:
|
|
return "custom"
|
|
|
|
|
|
def get_migration_info() -> str:
|
|
"""Get information about database migration setup.
|
|
|
|
Returns:
|
|
Migration setup information
|
|
"""
|
|
return """
|
|
Database Migration Information
|
|
==============================
|
|
|
|
Current Strategy: SQLAlchemy create_all()
|
|
- Automatically creates tables on startup
|
|
- Suitable for development and single-instance deployments
|
|
- Schema changes require manual handling
|
|
|
|
For Production Migrations (Alembic):
|
|
====================================
|
|
|
|
1. Initialize Alembic:
|
|
alembic init alembic
|
|
|
|
2. Configure alembic/env.py:
|
|
- Import Base from src.server.database.base
|
|
- Set target_metadata = Base.metadata
|
|
|
|
3. Configure alembic.ini:
|
|
- Set sqlalchemy.url to your database URL
|
|
|
|
4. Generate initial migration:
|
|
alembic revision --autogenerate -m "Initial schema"
|
|
|
|
5. Apply migrations:
|
|
alembic upgrade head
|
|
|
|
6. For future changes:
|
|
- Modify models in src/server/database/models.py
|
|
- Generate migration: alembic revision --autogenerate -m "Description"
|
|
- Review generated migration in alembic/versions/
|
|
- Apply: alembic upgrade head
|
|
|
|
Benefits of Alembic:
|
|
- Version control for database schema
|
|
- Automatic migration generation from model changes
|
|
- Rollback support with downgrade scripts
|
|
- Multi-instance deployment support
|
|
- Safe schema changes in production
|
|
"""
|
|
|
|
|
|
# =============================================================================
|
|
# Future Alembic Integration
|
|
# =============================================================================
|
|
#
|
|
# When ready to use Alembic, follow these steps:
|
|
#
|
|
# 1. Install Alembic (already in requirements.txt):
|
|
# pip install alembic
|
|
#
|
|
# 2. Initialize Alembic from project root:
|
|
# alembic init alembic
|
|
#
|
|
# 3. Update alembic/env.py to use our Base:
|
|
# from src.server.database.base import Base
|
|
# target_metadata = Base.metadata
|
|
#
|
|
# 4. Configure alembic.ini with DATABASE_URL from settings
|
|
#
|
|
# 5. Generate initial migration:
|
|
# alembic revision --autogenerate -m "Initial schema"
|
|
#
|
|
# 6. Review generated migration and apply:
|
|
# alembic upgrade head
|
|
#
|
|
# =============================================================================
|