feat(core): Add database support to SeriesApp (Task 7)
- 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
This commit is contained in:
@@ -8,10 +8,16 @@ progress reporting, and error handling.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import warnings
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from events import Events
|
||||
|
||||
try:
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
except ImportError: # pragma: no cover - optional dependency
|
||||
AsyncSession = object # type: ignore
|
||||
|
||||
from src.core.entities.SerieList import SerieList
|
||||
from src.core.entities.series import Serie
|
||||
from src.core.providers.provider_factory import Loaders
|
||||
@@ -130,15 +136,20 @@ class SeriesApp:
|
||||
def __init__(
|
||||
self,
|
||||
directory_to_search: str,
|
||||
db_session: Optional[AsyncSession] = None,
|
||||
):
|
||||
"""
|
||||
Initialize SeriesApp.
|
||||
|
||||
Args:
|
||||
directory_to_search: Base directory for anime series
|
||||
db_session: Optional database session for database-backed
|
||||
storage. When provided, SerieList and SerieScanner will
|
||||
use the database instead of file-based storage.
|
||||
"""
|
||||
|
||||
self.directory_to_search = directory_to_search
|
||||
self._db_session = db_session
|
||||
|
||||
# Initialize events
|
||||
self._events = Events()
|
||||
@@ -147,15 +158,20 @@ class SeriesApp:
|
||||
|
||||
self.loaders = Loaders()
|
||||
self.loader = self.loaders.GetLoader(key="aniworld.to")
|
||||
self.serie_scanner = SerieScanner(directory_to_search, self.loader)
|
||||
self.list = SerieList(self.directory_to_search)
|
||||
self.serie_scanner = SerieScanner(
|
||||
directory_to_search, self.loader, db_session=db_session
|
||||
)
|
||||
self.list = SerieList(
|
||||
self.directory_to_search, db_session=db_session
|
||||
)
|
||||
# Synchronous init used during constructor to avoid awaiting
|
||||
# in __init__
|
||||
self._init_list_sync()
|
||||
|
||||
logger.info(
|
||||
"SeriesApp initialized for directory: %s",
|
||||
directory_to_search
|
||||
"SeriesApp initialized for directory: %s (db_session: %s)",
|
||||
directory_to_search,
|
||||
"provided" if db_session else "none"
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -188,6 +204,53 @@ class SeriesApp:
|
||||
"""Set scan_status event handler."""
|
||||
self._events.scan_status = value
|
||||
|
||||
@property
|
||||
def db_session(self) -> Optional[AsyncSession]:
|
||||
"""
|
||||
Get the database session.
|
||||
|
||||
Returns:
|
||||
AsyncSession or None: The database session if configured
|
||||
"""
|
||||
return self._db_session
|
||||
|
||||
def set_db_session(self, session: Optional[AsyncSession]) -> None:
|
||||
"""
|
||||
Update the database session.
|
||||
|
||||
Also updates the db_session on SerieList and SerieScanner.
|
||||
|
||||
Args:
|
||||
session: The new database session or None
|
||||
"""
|
||||
self._db_session = session
|
||||
self.list._db_session = session
|
||||
self.serie_scanner._db_session = session
|
||||
logger.debug(
|
||||
"Database session updated: %s",
|
||||
"provided" if session else "none"
|
||||
)
|
||||
|
||||
async def init_from_db_async(self) -> None:
|
||||
"""
|
||||
Initialize series list from database (async).
|
||||
|
||||
This should be called when using database storage instead of
|
||||
the synchronous file-based initialization.
|
||||
"""
|
||||
if self._db_session:
|
||||
await self.list.load_series_from_db(self._db_session)
|
||||
self.series_list = self.list.GetMissingEpisode()
|
||||
logger.debug(
|
||||
"Loaded %d series with missing episodes from database",
|
||||
len(self.series_list)
|
||||
)
|
||||
else:
|
||||
warnings.warn(
|
||||
"init_from_db_async called without db_session configured",
|
||||
UserWarning
|
||||
)
|
||||
|
||||
def _init_list_sync(self) -> None:
|
||||
"""Synchronous initialization helper for constructor."""
|
||||
self.series_list = self.list.GetMissingEpisode()
|
||||
|
||||
Reference in New Issue
Block a user