- Added db_session parameter to SeriesApp.__init__() - Added db_session property and set_db_session() method - Added init_from_db_async() for async database initialization - Pass db_session to SerieList and SerieScanner during construction - Added get_series_app_with_db() dependency for FastAPI endpoints - All 815 unit tests and 55 API tests pass
16 KiB
Aniworld Web Application Development Instructions
This document provides detailed tasks for AI agents to implement a modern web application for the Aniworld anime download manager. All tasks should follow the coding guidelines specified in the project's copilot instructions.
Project Overview
The goal is to create a FastAPI-based web application that provides a modern interface for the existing Aniworld anime download functionality. The core anime logic should remain in SeriesApp.py while the web layer provides REST API endpoints and a responsive UI.
Architecture Principles
- Single Responsibility: Each file/class has one clear purpose
- Dependency Injection: Use FastAPI's dependency system
- Clean Separation: Web layer calls core logic, never the reverse
- File Size Limit: Maximum 500 lines per file
- Type Hints: Use comprehensive type annotations
- Error Handling: Proper exception handling and logging
Additional Implementation Guidelines
Code Style and Standards
- Type Hints: Use comprehensive type annotations throughout all modules
- Docstrings: Follow PEP 257 for function and class documentation
- Error Handling: Implement custom exception classes with meaningful messages
- Logging: Use structured logging with appropriate log levels
- Security: Validate all inputs and sanitize outputs
- Performance: Use async/await patterns for I/O operations
📞 Escalation
If you encounter:
- Architecture issues requiring design decisions
- Tests that conflict with documented requirements
- Breaking changes needed
- Unclear requirements or expectations
Document the issue and escalate rather than guessing.
🎯 Current Task: Migrate Series Data from File Storage to Database
Background
The current implementation stores anime series metadata in data files (JSON format without .json extension) located in each series folder (e.g., {anime_directory}/{series_folder}/data). This task migrates that storage to the SQLite database using the existing AnimeSeries model.
Files Involved
Current Data File Storage:
src/core/entities/series.py-Serieclass withsave_to_file()andload_from_file()methodssrc/core/entities/SerieList.py-SerieListclass that loads/saves data filessrc/core/SerieScanner.py- Scanner that creates data files during scan
Database Components (Already Exist):
src/server/database/models.py-AnimeSeriesmodel (already defined)src/server/database/service.py-AnimeSeriesServicewith CRUD operationssrc/server/database/init.py- Database initialization
API Endpoints:
src/server/api/anime.py-/api/anime/addendpoint that adds new series
Task 1: Create Data File Migration Service ✅
File: src/server/services/data_migration_service.py
Description: Create a service that migrates existing data files to the database.
Requirements:
-
Create
DataMigrationServiceclass with the following methods:scan_for_data_files(anime_directory: str) -> List[Path]- Find alldatafiles in the anime directorymigrate_data_file(data_path: Path, db: AsyncSession) -> bool- Migrate single data file to DBmigrate_all(anime_directory: str, db: AsyncSession) -> MigrationResult- Migrate all found data filesis_migration_needed(anime_directory: str) -> bool- Check if there are data files to migrate
-
Migration logic:
- Read the
datafile usingSerie.load_from_file() - Check if series with same
keyalready exists in DB usingAnimeSeriesService.get_by_key() - If not exists, create new
AnimeSeriesrecord usingAnimeSeriesService.create() - If exists, optionally update the
episode_dictif it has changed - Log all operations with appropriate log levels
- Read the
-
Create
MigrationResultdataclass:@dataclass class MigrationResult: total_found: int migrated: int skipped: int failed: int errors: List[str] -
Handle errors gracefully - don't stop migration on individual file failures
Testing Requirements:
- Unit tests in
tests/unit/test_data_migration_service.py - Test data file scanning
- Test single file migration
- Test migration when series already exists
- Test error handling for corrupted files
Task 2: Create Startup Migration Script ✅
File: src/server/services/startup_migration.py
Description: Create a migration runner that executes on every application startup.
Requirements:
-
Create
run_startup_migration(anime_directory: str) -> MigrationResultasync function -
This function should:
- Check if migration is needed using
DataMigrationService.is_migration_needed() - If needed, run
DataMigrationService.migrate_all() - Log migration results
- Return the
MigrationResult
- Check if migration is needed using
-
Create
ensure_migration_on_startup()async function that:- Gets the anime directory from settings/config
- Runs
run_startup_migration()if directory is configured - Handles cases where directory is not yet configured (first run)
Testing Requirements:
- Unit tests in
tests/unit/test_startup_migration.py - Test migration runs when data files exist
- Test migration skips when no data files exist
- Test handling of unconfigured anime directory
Task 3: Integrate Migration into FastAPI Lifespan ✅
File: src/server/fastapi_app.py
Description: Add the startup migration to the FastAPI application lifespan.
Requirements:
- Import
ensure_migration_on_startupfrom startup migration service - Call
await ensure_migration_on_startup()in thelifespanfunction after config is loaded - Log migration results
- Do NOT block application startup on migration failure - log error and continue
Example Integration:
@asynccontextmanager
async def lifespan(app: FastAPI):
# ... existing startup code ...
# Run data file to database migration
try:
from src.server.services.startup_migration import ensure_migration_on_startup
migration_result = await ensure_migration_on_startup()
if migration_result:
logger.info(
"Data migration complete: %d migrated, %d skipped, %d failed",
migration_result.migrated,
migration_result.skipped,
migration_result.failed
)
except Exception as e:
logger.error("Data migration failed: %s", e, exc_info=True)
# Continue startup - migration failure should not block app
# ... rest of startup ...
Testing Requirements:
- Integration test that verifies migration runs on startup
- Test that app starts even if migration fails
Task 4: Update SerieList to Use Database ✅
File: src/core/entities/SerieList.py
Description: Modify SerieList class to read from database instead of data files.
Requirements:
-
Add optional
db_sessionparameter to__init__ -
Modify
load_series()method:- If
db_sessionis provided, load from database usingAnimeSeriesService.get_all() - Convert
AnimeSeriesmodels toSerieobjects - Fall back to file-based loading if no
db_session(for backward compatibility)
- If
-
Modify
add()method:- If
db_sessionis provided, save to database usingAnimeSeriesService.create() - Do NOT create data files anymore
- Fall back to file-based saving if no
db_session
- If
-
Add new method
load_series_from_db(db: AsyncSession) -> None -
Add new method
add_to_db(serie: Serie, db: AsyncSession) -> None
Important: Keep backward compatibility - file-based operations should still work when no db_session is provided.
Testing Requirements:
- Unit tests for database-based loading
- Unit tests for database-based adding
- Test backward compatibility with file-based operations
- Test conversion between
AnimeSeriesmodel andSerieentity
Task 5: Update SerieScanner to Use Database ✅
File: src/core/SerieScanner.py
Description: Modify SerieScanner to save scan results to database instead of data files.
Requirements:
-
Add optional
db_sessionparameter to__init__ -
Modify scanning logic (around line 185-188):
- If
db_sessionis provided, save to database instead of file - Use
AnimeSeriesService.create()orAnimeSeriesService.update()for upserting - Do NOT create data files anymore when using database
- If
-
Create helper method
_save_serie_to_db(serie: Serie, db: AsyncSession) -> None -
Create helper method
_update_serie_in_db(serie: Serie, db: AsyncSession) -> None
Important: Keep backward compatibility for CLI usage without database.
Testing Requirements:
- Unit tests for database-based saving during scan
- Test that scan results persist to database
- Test upsert behavior (update existing series)
Task 6: Update Anime API Endpoints ✅
File: src/server/api/anime.py
Description: Update the /api/anime/add endpoint to save to database instead of file.
Requirements:
-
Modify
add_series()endpoint:- Get database session using dependency injection
- Use
AnimeSeriesService.create()to save new series - Remove or replace file-based
series_app.list.add(serie)call - Return the created series info including database ID
-
Add database session dependency:
from src.server.database import get_db_session @router.post("/add") async def add_series( request: AddSeriesRequest, _auth: dict = Depends(require_auth), series_app: Any = Depends(get_series_app), db: AsyncSession = Depends(get_db_session), ) -> dict: -
Update list/get endpoints to optionally read from database
Testing Requirements:
- API test for adding series via database
- Test that added series appears in database
- Test duplicate key handling
Implementation Notes:
- Added
get_optional_database_session()dependency independencies.pyfor graceful fallback - Endpoint saves to database when available, falls back to file-based storage when not
- All 55 API tests and 809 unit tests pass
Task 7: Update Dependencies and SeriesApp ⬜
File: src/server/utils/dependencies.py and src/core/SeriesApp.py
Description: Update dependency injection to provide database sessions to core components.
Requirements:
-
Update
get_series_app()dependency:- Initialize
SerieListwith database session when available - Pass database session to
SerieScannerwhen available
- Initialize
-
Create
get_series_app_with_db()dependency that provides database-awareSeriesApp -
Update
SeriesApp.__init__():- Add optional
db_sessionparameter - Pass to
SerieListandSerieScanner
- Add optional
Testing Requirements:
- Test
SeriesAppinitialization with database session - Test dependency injection provides correct sessions
Task 8: Write Integration Tests ⬜
File: tests/integration/test_data_file_migration.py
Description: Create comprehensive integration tests for the migration workflow.
Test Cases:
test_migration_on_fresh_start- No data files, no database entriestest_migration_with_existing_data_files- Data files exist, migrate to DBtest_migration_skips_existing_db_entries- Series already in DB, skip migrationtest_add_series_saves_to_database- New series via API saves to DBtest_scan_saves_to_database- Scan results save to DBtest_list_reads_from_database- Series list reads from DBtest_search_and_add_workflow- Search -> Add -> Verify in DB
Setup:
- Use pytest fixtures with temporary directories
- Use test database (in-memory SQLite)
- Create sample data files for migration tests
Task 9: Clean Up Legacy Code ⬜
Description: Remove or deprecate file-based storage code after database migration is stable.
Requirements:
-
Add deprecation warnings to file-based methods:
Serie.save_to_file()- Addwarnings.warn()with deprecation noticeSerie.load_from_file()- Addwarnings.warn()with deprecation noticeSerieList.add()file path - Log deprecation when creating data files
-
Update documentation:
- Document that data files are deprecated
- Document database storage as the primary method
- Update
infrastructure.mdwith new architecture
-
Do NOT remove file-based code yet - keep for backward compatibility
Testing Requirements:
- Test that deprecation warnings are raised
- Verify existing file-based tests still pass
Task 10: Final Validation ⬜
Description: Validate the complete migration implementation.
Validation Checklist:
- All unit tests pass:
conda run -n AniWorld python -m pytest tests/unit/ -v - All integration tests pass:
conda run -n AniWorld python -m pytest tests/integration/ -v - All API tests pass:
conda run -n AniWorld python -m pytest tests/api/ -v - Migration runs automatically on server startup
- New series added via API are saved to database
- Scan results are saved to database
- Series list is read from database
- Existing data files are migrated to database on first run
- Application starts successfully even with no data files
- Application starts successfully even with no anime directory configured
- Deprecation warnings appear in logs when file-based methods are used
- No new data files are created after migration
Manual Testing:
- Start fresh server:
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload - Login and configure anime directory
- Run rescan - verify series appear in database
- Search and add new series - verify saved to database
- Restart server - verify migration detects no new files to migrate
- Check database for all series entries
📚 Helpful Commands
# Run all tests
conda run -n AniWorld python -m pytest tests/ -v --tb=short
# Run specific test file
conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py -v
# Run specific test class
conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py::TestWebSocketService -v
# Run specific test
conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py::TestWebSocketService::test_broadcast_download_progress -v
# Run with extra verbosity
conda run -n AniWorld python -m pytest tests/ -vv
# Run with full traceback
conda run -n AniWorld python -m pytest tests/ -v --tb=long
# Run and stop at first failure
conda run -n AniWorld python -m pytest tests/ -v -x
# Run tests matching pattern
conda run -n AniWorld python -m pytest tests/ -v -k "auth"
# Show all print statements
conda run -n AniWorld python -m pytest tests/ -v -s
#Run app
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload
Final Implementation Notes
- Incremental Development: Implement features incrementally, testing each component thoroughly before moving to the next
- Code Review: Review all generated code for adherence to project standards
- Documentation: Document all public APIs and complex logic
- Testing: Maintain test coverage above 80% for all new code
- Performance: Profile and optimize critical paths, especially download and streaming operations
- Security: Regular security audits and dependency updates
- Monitoring: Implement comprehensive monitoring and alerting
- Maintenance: Plan for regular maintenance and updates
Task Completion Checklist
For each task completed:
- Implementation follows coding standards
- Unit tests written and passing
- Integration tests passing
- Documentation updated
- Error handling implemented
- Logging added
- Security considerations addressed
- Performance validated
- Code reviewed
- Task marked as complete in instructions.md
- Infrastructure.md updated
- Changes committed to git; keep your messages in git short and clear
- Take the next task
Prerequisites
- Server is running:
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload - Password:
Hallo123! - Login via browser at
http://127.0.0.1:8000/login
Notes
- This is a simplification that removes complexity while maintaining core functionality
- Improves user experience with explicit manual control
- Easier to understand, test, and maintain
- Good foundation for future enhancements if needed