cleanup
This commit is contained in:
@@ -5,7 +5,7 @@ This module provides dependency injection functions for the FastAPI
|
||||
application, including SeriesApp instances, AnimeService, DownloadService,
|
||||
database sessions, and authentication dependencies.
|
||||
"""
|
||||
from typing import AsyncGenerator, Optional
|
||||
from typing import TYPE_CHECKING, AsyncGenerator, Optional
|
||||
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
@@ -19,6 +19,10 @@ from src.config.settings import settings
|
||||
from src.core.SeriesApp import SeriesApp
|
||||
from src.server.services.auth_service import AuthError, auth_service
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.server.services.anime_service import AnimeService
|
||||
from src.server.services.download_service import DownloadService
|
||||
|
||||
# Security scheme for JWT authentication
|
||||
# Use auto_error=False to handle errors manually and return 401 instead of 403
|
||||
security = HTTPBearer(auto_error=False)
|
||||
@@ -28,8 +32,8 @@ security = HTTPBearer(auto_error=False)
|
||||
_series_app: Optional[SeriesApp] = None
|
||||
|
||||
# Global service instances
|
||||
_anime_service: Optional[object] = None
|
||||
_download_service: Optional[object] = None
|
||||
_anime_service: Optional["AnimeService"] = None
|
||||
_download_service: Optional["DownloadService"] = None
|
||||
|
||||
|
||||
def get_series_app() -> SeriesApp:
|
||||
@@ -193,7 +197,13 @@ def get_current_user_optional(
|
||||
class CommonQueryParams:
|
||||
"""Common query parameters for API endpoints."""
|
||||
|
||||
def __init__(self, skip: int = 0, limit: int = 100):
|
||||
def __init__(self, skip: int = 0, limit: int = 100) -> None:
|
||||
"""Create a reusable pagination parameter container.
|
||||
|
||||
Args:
|
||||
skip: Number of records to offset when querying collections.
|
||||
limit: Maximum number of records to return in a single call.
|
||||
"""
|
||||
self.skip = skip
|
||||
self.limit = limit
|
||||
|
||||
@@ -235,7 +245,7 @@ async def log_request_dependency():
|
||||
pass
|
||||
|
||||
|
||||
def get_anime_service() -> object:
|
||||
def get_anime_service() -> "AnimeService":
|
||||
"""
|
||||
Dependency to get AnimeService instance.
|
||||
|
||||
@@ -257,29 +267,39 @@ def get_anime_service() -> object:
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
running_tests = "PYTEST_CURRENT_TEST" in os.environ or "pytest" in sys.modules
|
||||
running_tests = (
|
||||
"PYTEST_CURRENT_TEST" in os.environ
|
||||
or "pytest" in sys.modules
|
||||
)
|
||||
if running_tests:
|
||||
settings.anime_directory = tempfile.gettempdir()
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Anime directory not configured. Please complete setup.",
|
||||
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)}",
|
||||
detail=(
|
||||
"Failed to initialize AnimeService: "
|
||||
f"{str(e)}"
|
||||
),
|
||||
) from e
|
||||
|
||||
return _anime_service
|
||||
|
||||
|
||||
def get_download_service() -> object:
|
||||
def get_download_service() -> "DownloadService":
|
||||
"""
|
||||
Dependency to get DownloadService instance.
|
||||
|
||||
@@ -293,46 +313,49 @@ def get_download_service() -> object:
|
||||
|
||||
if _download_service is None:
|
||||
try:
|
||||
from src.server.services import (
|
||||
websocket_service as websocket_service_module,
|
||||
)
|
||||
from src.server.services.download_service import DownloadService
|
||||
from src.server.services.websocket_service import get_websocket_service
|
||||
|
||||
# Get anime service first (required dependency)
|
||||
anime_service = get_anime_service()
|
||||
|
||||
# Initialize download service with anime service
|
||||
_download_service = DownloadService(anime_service)
|
||||
|
||||
# Setup WebSocket broadcast callback
|
||||
ws_service = get_websocket_service()
|
||||
|
||||
async def broadcast_callback(update_type: str, data: dict):
|
||||
|
||||
ws_service = websocket_service_module.get_websocket_service()
|
||||
|
||||
async def broadcast_callback(update_type: str, data: dict) -> None:
|
||||
"""Broadcast download updates via WebSocket."""
|
||||
if update_type == "download_progress":
|
||||
await ws_service.broadcast_download_progress(
|
||||
data.get("download_id", ""), data
|
||||
data.get("download_id", ""),
|
||||
data,
|
||||
)
|
||||
elif update_type == "download_complete":
|
||||
await ws_service.broadcast_download_complete(
|
||||
data.get("download_id", ""), data
|
||||
data.get("download_id", ""),
|
||||
data,
|
||||
)
|
||||
elif update_type == "download_failed":
|
||||
await ws_service.broadcast_download_failed(
|
||||
data.get("download_id", ""), data
|
||||
data.get("download_id", ""),
|
||||
data,
|
||||
)
|
||||
elif update_type == "queue_status":
|
||||
await ws_service.broadcast_queue_status(data)
|
||||
else:
|
||||
# Generic queue update
|
||||
await ws_service.broadcast_queue_status(data)
|
||||
|
||||
|
||||
_download_service.set_broadcast_callback(broadcast_callback)
|
||||
|
||||
|
||||
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)}",
|
||||
detail=(
|
||||
"Failed to initialize DownloadService: "
|
||||
f"{str(e)}"
|
||||
),
|
||||
) from e
|
||||
|
||||
return _download_service
|
||||
|
||||
Reference in New Issue
Block a user