feat(scanner): add DB fallback for series key resolution
When SerieScanner encounters a folder without a local key or data file, it now optionally falls back to a database lookup by folder name. This prevents newly-added series from being silently skipped on rescan when their metadata only lives in the DB. Changes: - SerieScanner accepts an optional db_lookup callable - SeriesApp forwards db_lookup to SerieScanner - AnimeSeriesService adds get_by_folder_sync() helper - dependencies.py wires a sync DB lookup into get_series_app() - Unit tests cover fallback hit, miss, and exception paths
This commit is contained in:
@@ -15,7 +15,7 @@ import os
|
||||
import re
|
||||
import traceback
|
||||
import uuid
|
||||
from typing import Iterable, Iterator, Optional
|
||||
from typing import Callable, Iterable, Iterator, Optional
|
||||
|
||||
from events import Events
|
||||
|
||||
@@ -43,12 +43,17 @@ class SerieScanner:
|
||||
scanner = SerieScanner("/path/to/anime", loader)
|
||||
scanner.scan()
|
||||
# Results are in scanner.keyDict
|
||||
|
||||
# With DB lookup fallback:
|
||||
scanner = SerieScanner("/path/to/anime", loader,
|
||||
db_lookup=lambda folder: my_db.get_by_folder(folder))
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
basePath: str,
|
||||
loader: Loader,
|
||||
db_lookup: Optional[Callable[[str], Optional["Serie"]]] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Initialize the SerieScanner.
|
||||
@@ -56,8 +61,12 @@ class SerieScanner:
|
||||
Args:
|
||||
basePath: Base directory containing anime series
|
||||
loader: Loader instance for fetching series information
|
||||
callback_manager: Optional callback manager for progress updates
|
||||
|
||||
db_lookup: Optional callable ``(folder_name) -> Serie | None``.
|
||||
When provided, it is called as a fallback when neither a
|
||||
``key`` file nor a ``data`` file is found in the folder.
|
||||
This allows the database to supply the series key for
|
||||
folders that have never had a local key file.
|
||||
|
||||
Raises:
|
||||
ValueError: If basePath is invalid or doesn't exist
|
||||
"""
|
||||
@@ -75,6 +84,7 @@ class SerieScanner:
|
||||
self.directory: str = abs_path
|
||||
self.keyDict: dict[str, Serie] = {}
|
||||
self.loader: Loader = loader
|
||||
self._db_lookup: Optional[Callable[[str], Optional[Serie]]] = db_lookup
|
||||
self._current_operation_id: Optional[str] = None
|
||||
self.events = Events()
|
||||
|
||||
@@ -268,6 +278,30 @@ class SerieScanner:
|
||||
)
|
||||
|
||||
serie = self.__read_data_from_file(folder)
|
||||
if serie is None or not serie.key or not serie.key.strip():
|
||||
# Fallback: ask the database for a matching series
|
||||
if self._db_lookup is not None:
|
||||
try:
|
||||
serie = self._db_lookup(folder)
|
||||
if serie:
|
||||
logger.info(
|
||||
"DB lookup resolved folder '%s' -> key='%s'",
|
||||
folder,
|
||||
serie.key,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"DB lookup failed for folder '%s': %s",
|
||||
folder,
|
||||
exc,
|
||||
)
|
||||
serie = None
|
||||
|
||||
if serie is None or not serie.key or not serie.key.strip():
|
||||
logger.warning(
|
||||
"No key or data file found for folder '%s', skipping",
|
||||
folder,
|
||||
)
|
||||
if (
|
||||
serie is not None
|
||||
and serie.key
|
||||
|
||||
Reference in New Issue
Block a user