feat: Implement download queue API endpoints
- Add comprehensive REST API for download queue management
- Implement GET /api/queue/status endpoint with queue status and statistics
- Implement POST /api/queue/add for adding episodes to queue with priority support
- Implement DELETE /api/queue/{id} and DELETE /api/queue/ for removing items
- Implement POST /api/queue/start and /api/queue/stop for queue control
- Implement POST /api/queue/pause and /api/queue/resume for pause/resume
- Implement POST /api/queue/reorder for queue item reordering
- Implement DELETE /api/queue/completed for clearing completed items
- Implement POST /api/queue/retry for retrying failed downloads
- Add get_download_service and get_anime_service dependencies
- Register download router in FastAPI application
- Add comprehensive test suite for all endpoints
- All endpoints require JWT authentication
- Update infrastructure documentation
- Remove completed task from instructions.md
Follows REST conventions with proper error handling and status codes.
Tests cover success cases, error conditions, and authentication requirements.
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
Dependency injection utilities for FastAPI.
|
||||
|
||||
This module provides dependency injection functions for the FastAPI
|
||||
application, including SeriesApp instances, database sessions, and
|
||||
authentication dependencies.
|
||||
application, including SeriesApp instances, AnimeService, DownloadService,
|
||||
database sessions, and authentication dependencies.
|
||||
"""
|
||||
from typing import AsyncGenerator, Optional
|
||||
|
||||
@@ -26,6 +26,10 @@ security = HTTPBearer()
|
||||
# Global SeriesApp instance
|
||||
_series_app: Optional[SeriesApp] = None
|
||||
|
||||
# Global service instances
|
||||
_anime_service: Optional[object] = None
|
||||
_download_service: Optional[object] = None
|
||||
|
||||
|
||||
def get_series_app() -> SeriesApp:
|
||||
"""
|
||||
@@ -193,3 +197,79 @@ async def log_request_dependency():
|
||||
TODO: Implement request logging logic
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def get_anime_service() -> object:
|
||||
"""
|
||||
Dependency to get AnimeService instance.
|
||||
|
||||
Returns:
|
||||
AnimeService: The anime service for async operations
|
||||
|
||||
Raises:
|
||||
HTTPException: If anime directory is not configured or
|
||||
AnimeService initialization fails
|
||||
"""
|
||||
global _anime_service
|
||||
|
||||
if not settings.anime_directory:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Anime directory not configured. Please complete setup.",
|
||||
)
|
||||
|
||||
if _anime_service is None:
|
||||
try:
|
||||
from src.server.services.anime_service import AnimeService
|
||||
_anime_service = AnimeService(settings.anime_directory)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to initialize AnimeService: {str(e)}",
|
||||
) from e
|
||||
|
||||
return _anime_service
|
||||
|
||||
|
||||
def get_download_service() -> object:
|
||||
"""
|
||||
Dependency to get DownloadService instance.
|
||||
|
||||
Returns:
|
||||
DownloadService: The download queue service
|
||||
|
||||
Raises:
|
||||
HTTPException: If DownloadService initialization fails
|
||||
"""
|
||||
global _download_service
|
||||
|
||||
if _download_service is None:
|
||||
try:
|
||||
from src.server.services.download_service import DownloadService
|
||||
|
||||
# Get anime service first (required dependency)
|
||||
anime_service = get_anime_service()
|
||||
|
||||
# Initialize download service with anime service
|
||||
_download_service = DownloadService(anime_service)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to initialize DownloadService: {str(e)}",
|
||||
) from e
|
||||
|
||||
return _download_service
|
||||
|
||||
|
||||
def reset_anime_service() -> None:
|
||||
"""Reset global AnimeService instance (for testing/config changes)."""
|
||||
global _anime_service
|
||||
_anime_service = None
|
||||
|
||||
|
||||
def reset_download_service() -> None:
|
||||
"""Reset global DownloadService instance (for testing/config changes)."""
|
||||
global _download_service
|
||||
_download_service = None
|
||||
|
||||
Reference in New Issue
Block a user