Remove redundant episode loading step

- Merged _load_episodes() functionality into _scan_missing_episodes()
- _scan_missing_episodes() already queries provider and compares with filesystem
- Eliminates duplicate filesystem scanning during series add
- Simplifies background loading flow: NFO → Episode Discovery
This commit is contained in:
2026-01-23 18:26:36 +01:00
parent 0e58a49cdd
commit 800790fc8f
3 changed files with 171 additions and 9 deletions

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import asyncio
import time
from datetime import datetime, timezone
from functools import lru_cache
from typing import Optional
@@ -733,6 +734,98 @@ class AnimeService:
# Load into SeriesApp
self._app.load_series_from_list(series_list)
async def sync_episodes_to_db(self, series_key: str) -> int:
"""
Sync episodes from in-memory SeriesApp to database for a specific series.
This method reads the episodeDict from the in-memory series (populated
by scanner) and syncs it to the database. Called after scanning for
missing episodes.
Args:
series_key: The series key to sync episodes for
Returns:
Number of episodes synced to database
"""
from src.server.database.connection import get_db_session
from src.server.database.service import AnimeSeriesService, EpisodeService
# Get the serie from in-memory cache
if not hasattr(self._app, 'list') or not hasattr(self._app.list, 'keyDict'):
logger.warning(f"Series list not available for episode sync: {series_key}")
return 0
serie = self._app.list.keyDict.get(series_key)
if not serie:
logger.warning(f"Series not found in memory for episode sync: {series_key}")
return 0
episodes_added = 0
async with get_db_session() as db:
# Get series from database
series_db = await AnimeSeriesService.get_by_key(db, series_key)
if not series_db:
logger.warning(f"Series not found in database: {series_key}")
return 0
# Get existing episodes from database
existing_episodes = await EpisodeService.get_by_series(db, series_db.id)
# Build dict of existing episodes: {season: {ep_num: episode_id}}
existing_dict: dict[int, dict[int, int]] = {}
for ep in existing_episodes:
if ep.season not in existing_dict:
existing_dict[ep.season] = {}
existing_dict[ep.season][ep.episode_number] = ep.id
# Get new missing episodes from in-memory serie
new_dict = serie.episodeDict or {}
# Add new missing episodes that are not in the database
for season, episode_numbers in new_dict.items():
existing_season_eps = existing_dict.get(season, {})
for ep_num in episode_numbers:
if ep_num not in existing_season_eps:
await EpisodeService.create(
db=db,
series_id=series_db.id,
season=season,
episode_number=ep_num,
)
episodes_added += 1
logger.debug(
f"Added missing episode to database: {series_key} S{season:02d}E{ep_num:02d}"
)
if episodes_added > 0:
logger.info(
f"Synced {episodes_added} missing episodes to database for {series_key}"
)
# Broadcast update to frontend to refresh series list
try:
await self._broadcast_series_updated(series_key)
except Exception as e:
logger.warning(f"Failed to broadcast series update: {e}")
return episodes_added
async def _broadcast_series_updated(self, series_key: str) -> None:
"""Broadcast series update event to WebSocket clients."""
if not self._websocket_service:
return
payload = {
"type": "series_updated",
"key": series_key,
"message": "Episodes updated",
"timestamp": datetime.now(timezone.utc).isoformat()
}
await self._websocket_service.broadcast(payload)
async def add_series_to_db(
self,
serie,