Remove legacy key file support after DB migration
- SerieScanner: Remove key file fallback, keep data file fallback - SystemSettings: Add legacy_key_cleanup_completed flag - initialization_service: Add cleanup task to remove key files from folders with DB entries - Tests updated to reflect key file removal from legacy path Key files caused duplicate key errors on folder rename. DB is now sole source of truth.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""Centralized initialization service for application startup and setup."""
|
||||
import asyncio
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
@@ -122,6 +123,28 @@ async def _mark_legacy_migration_completed() -> None:
|
||||
)
|
||||
|
||||
|
||||
async def _check_legacy_key_cleanup_status() -> bool:
|
||||
"""Check if legacy key file cleanup has been completed.
|
||||
|
||||
Returns:
|
||||
bool: True if cleanup was completed, False otherwise
|
||||
"""
|
||||
return await _check_scan_status(
|
||||
check_method=lambda svc, db: svc.is_legacy_key_cleanup_completed(db),
|
||||
scan_type="legacy_key_cleanup",
|
||||
log_completed_msg="Legacy key file cleanup already completed, skipping",
|
||||
log_not_completed_msg="Legacy key file cleanup not yet run, will clean up key files"
|
||||
)
|
||||
|
||||
|
||||
async def _mark_legacy_key_cleanup_completed() -> None:
|
||||
"""Mark the legacy key file cleanup as completed in system settings."""
|
||||
await _mark_scan_completed(
|
||||
mark_method=lambda svc, db: svc.mark_legacy_key_cleanup_completed(db),
|
||||
scan_type="legacy_key_cleanup"
|
||||
)
|
||||
|
||||
|
||||
async def _migrate_legacy_files() -> int:
|
||||
"""Migrate series from legacy key/data files to database.
|
||||
|
||||
@@ -151,6 +174,78 @@ async def _migrate_legacy_files() -> int:
|
||||
return 0
|
||||
|
||||
|
||||
async def _cleanup_legacy_key_files() -> int:
|
||||
"""Remove legacy key files from folders that already have DB entries.
|
||||
|
||||
This is a one-time cleanup task that runs at startup after legacy migration.
|
||||
It removes deprecated 'key' files that cause duplicate key errors when
|
||||
folders are renamed, since the DB is now the source of truth.
|
||||
|
||||
Returns:
|
||||
int: Number of key files deleted
|
||||
"""
|
||||
from src.server.database.connection import get_db_session
|
||||
from src.server.database.service import AnimeSeriesService
|
||||
|
||||
logger.info("Checking for legacy key files to clean up...")
|
||||
|
||||
if not settings.anime_directory or not os.path.isdir(settings.anime_directory):
|
||||
logger.warning(
|
||||
"Anime directory not configured or does not exist, skipping legacy key cleanup"
|
||||
)
|
||||
return 0
|
||||
|
||||
deleted_count = 0
|
||||
scanned_count = 0
|
||||
|
||||
try:
|
||||
async with get_db_session() as db:
|
||||
# Get all series from DB to know which folders should have key files removed
|
||||
all_series = await AnimeSeriesService.get_all(db)
|
||||
|
||||
# Build a set of known folder names from DB
|
||||
db_folders: set[str] = {series.folder for series in all_series if series.folder}
|
||||
|
||||
for folder_name in db_folders:
|
||||
folder_path = settings.anime_directory / folder_name
|
||||
key_file = folder_path / "key"
|
||||
|
||||
if not key_file.exists():
|
||||
continue
|
||||
|
||||
scanned_count += 1
|
||||
try:
|
||||
key_file.unlink()
|
||||
deleted_count += 1
|
||||
logger.info(
|
||||
"Removed legacy key file",
|
||||
folder=folder_name,
|
||||
key_file=str(key_file)
|
||||
)
|
||||
except OSError as exc:
|
||||
logger.warning(
|
||||
"Could not remove legacy key file",
|
||||
folder=folder_name,
|
||||
key_file=str(key_file),
|
||||
error=str(exc)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
"Legacy key file cleanup failed",
|
||||
error=str(e),
|
||||
exc_info=True
|
||||
)
|
||||
return deleted_count
|
||||
|
||||
logger.info(
|
||||
"Legacy key file cleanup complete",
|
||||
scanned=scanned_count,
|
||||
deleted=deleted_count
|
||||
)
|
||||
return deleted_count
|
||||
|
||||
|
||||
async def _sync_anime_folders(progress_service=None) -> int:
|
||||
"""Scan anime folders and sync series to database.
|
||||
|
||||
@@ -287,6 +382,13 @@ async def perform_initial_setup(progress_service=None):
|
||||
# Sync series from anime folders to database
|
||||
await _sync_anime_folders(progress_service)
|
||||
|
||||
# Clean up legacy key files from folders that now have DB entries
|
||||
# This runs after migration/sync to ensure DB entries exist before deletion
|
||||
is_key_cleanup_done = await _check_legacy_key_cleanup_status()
|
||||
if not is_key_cleanup_done:
|
||||
await _cleanup_legacy_key_files()
|
||||
await _mark_legacy_key_cleanup_completed()
|
||||
|
||||
# Mark the initial scan as completed
|
||||
await _mark_initial_scan_completed()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user