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
Moves perform_nfo_repair_scan and its helpers (_repair_one_series,
_NFO_REPAIR_SEMAPHORE) into folder_scan_service.py so NFO repair runs
during the scheduled folder scan instead of on startup.
- Removes NFO repair code from initialization_service.py
- Updates all test imports and patch targets
- Updates docs/NFO_GUIDE.md and docs/CHANGELOG.md references
All 174 related tests pass.
- Add missing TMDB async mock methods (_ensure_session, close)
to all TMDB mocks in test_nfo_workflow.py
- Refactor test_anime_add_nfo_isolation.py to mock get_nfo_factory()
instead of asserting on series_app.nfo_service directly
- Patch get_nfo_factory in test_background_loader_service.py
to align with factory-based NFOService creation
Fixes test failures caused by NFOService refactoring that introduced
explicit TMDB session lifecycle and NFO factory pattern.
Add comprehensive test coverage for Tasks 1.1–1.5 and 2.1:
- test_scheduler_config_model.py: folder_scan_enabled defaults, explicit
values, backward compatibility with old configs, serialization roundtrip
- test_folder_scan_service.py (new): prerequisites, NFO repair integration,
folder rename integration, poster check/download, semaphore values,
NFO thumb URL extraction, full end-to-end scan flow
- test_scheduler_service.py: scheduler _perform_rescan integration with
folder_scan_enabled (called when enabled, skipped when disabled, error
handling and broadcasting), folder_scan_enabled in get_status output
- test_nfo_repair_startup.py: verify perform_nfo_repair_scan is NOT called
during FastAPI lifespan startup and IS called from FolderScanService
All 90 tests pass.
- Fix structlog format string in folder_scan_service (%(key)d -> kwargs)
- Add nfo_download_poster setting check before poster download
- Create missing NFO fixture files (tvshow.nfo.bad/good) for repair tests
- Fix test_context_used_in_logging to check all call args not format string
- Fix test_system_settings_integration isolation via reset_all_scans
- Add FolderScanService.run_folder_scan() calling perform_nfo_repair_scan()
- Remove startup-time NFO repair from fastapi_app lifespan
- Update docs/NFO_GUIDE.md: repair now runs as part of daily scan
- Update tests to verify integration wiring
- Update ARCHITECTURE.md and scheduler_service for scan scheduling
- Add showtitle and namedseason to mapper output
- Add multi-language fallback (en-US, ja-JP) for empty overview
- Use search result overview as last resort fallback
- Add tests for new NFO creation behavior
- Fixed _remove_episode_from_missing_list to also update in-memory
Serie.episodeDict and refresh series_list
- Added _remove_episode_from_memory helper method
- Enhanced logging for download completion and episode removal
- Added 5 unit tests for missing episode removal
When TMDB returns an empty German (de-DE) overview for anime (e.g.
Basilisk), the NFO plot tag was missing. Now both create and update
paths call _enrich_details_with_fallback() which fetches the English
(en-US) overview as a fallback.
Additionally, the <plot> XML element is always written (even when
empty) via the always_write parameter on _add_element(), ensuring
consistent NFO structure regardless of creation path.
Changes:
- nfo_service.py: add _enrich_details_with_fallback() method, call it
in create_tvshow_nfo and update_tvshow_nfo
- nfo_generator.py: add always_write param to _add_element(), use it
for <plot> tag
- test_nfo_service.py: add TestEnrichDetailsWithFallback with 4 tests
- Implement sync_single_series_after_scan to persist scanned series to database
- Enhanced _broadcast_series_updated to include full NFO metadata (nfo_created_at, nfo_updated_at, tmdb_id, tvdb_id)
- Add immediate episode scanning in add_series endpoint when background loader isn't running
- Implement updateSingleSeries in frontend to handle series_updated WebSocket events
- Add SERIES_UPDATED event constant to WebSocket event definitions
- Update background loader to use sync_single_series_after_scan method
- Simplified background loader initialization in FastAPI app
- Add comprehensive tests for series update WebSocket payload and episode counting logic
- Import reorganization: move get_background_loader_service to dependencies module
✅ COMPLETE: 18/18 tests passing
Test Coverage:
- Concurrent scan prevention: Second scan blocked, multiple attempts handled, lock released after completion
- Scan cancellation: Cancel active scan, cancel when none active, cancelled scans in history, new scan after cancellation
- Database race conditions: AsyncIO lock prevents races, scan state consistency with concurrent reads, thread-safe history updates
- Scan state consistency: is_scanning flag consistency, current_scan object consistency, status API consistency, concurrent status checks
- Scheduler prevention: Scheduler skips rescan if already running, properly sets scan_in_progress flag
- AnimeService: Ignores concurrent rescan requests
All concurrent operation scenarios validated with proper lock management and state consistency.
- Created tests/performance/test_nfo_batch_performance.py with 11 comprehensive tests
- Test classes: Concurrent NFO creation, TMDB API batching optimization, media download concurrency, memory usage, scalability
- Coverage: 10/50/100 series concurrent creation, TMDB API call optimization, rate limit handling, media downloads, memory efficiency, linear scalability
- Performance targets: 10 series < 5s, 50 series < 20s, 100 series < 30s - all met
- 11/11 tests passing - excellent performance coverage for batch operations
- Validates concurrent operations, API optimization, memory usage < 100MB for 100 series
- Created tests/performance/test_large_library.py with 12 comprehensive tests
- Test classes: Large library scanning, database query performance, memory usage, concurrent operations, scalability
- Coverage: 1000+ series scan benchmarks, memory limits (500MB), DB query performance, concurrent access, linear scalability
- 4/12 tests passing (memory efficient storage, concurrent DB operations, batch writes, scan handling)
- 8/12 tests need refinement (mocking issues similar to TMDB tests, DB initialization)
- Test logic and performance assertions are sound, only implementation details need work