Routes moved to thin parse-args/jsonify handlers; logic now lives in
six focused modules under core/search/. 720 lines deleted from
web_server.py; 109 added back as wrappers; ~700 lines of new core code
plus ~700 lines of tests.
Module split:
- core/search/cache.py — TTL+LRU cache for enhanced-search responses,
keyed by (query, active_server, fallback_source, hydrabase_active,
source_tag) so config changes don't poison stale entries.
- core/search/sources.py — per-kind metadata search (artists/albums/
tracks) and the multi-kind ThreadPoolExecutor that fans them out.
- core/search/library_check.py — library + wishlist presence check
with Plex thumb URL resolution; profile-aware wishlist with legacy
fallback for older DBs missing the profile_id column.
- core/search/stream.py — single-track preview search; effective stream
mode resolution, query-variant generation, retry walk, matching
engine integration.
- core/search/basic.py — flat Soulseek file search, quality-sorted.
- core/search/orchestrator.py — main enhanced-search dispatch
(short-query fast path, single-source bypass, hydrabase-primary fan
out, alternate source list builder), NDJSON streaming generator
for /source/<src>, and the SearchDeps dataclass that bundles the
cross-cutting deps.
Routes pass clients (spotify, hydrabase, hydrabase_worker, soulseek)
and helpers (config_manager, fix_artist_image_url,
_is_hydrabase_active, _get_metadata_fallback_*, _run_background_
comparison, run_async, dev_mode_enabled_provider) into core/search via
a SearchDeps bundle built per-request. fix_artist_image_url stays in
web_server.py because it touches 31 other call sites.
Behavior preserved 1:1:
- Same response shapes (db_artists, spotify_artists, spotify_albums,
spotify_tracks, primary_source, metadata_source, alternate_sources,
source_available)
- Same NDJSON line ordering (artists/albums/tracks as they finish, plus
done marker)
- Same per-kind exception swallowing
- Same hydrabase-worker mirror on dev mode
- Same cache key shape (5-tuple) and TTL/LRU semantics
- Same stream-track effective-mode resolution including the
Soulseek-coerce-to-YouTube edge case
- Same library-check Plex thumb URL rewriting and wishlist fallback
for older DBs
Tests: 94 new (cache TTL/LRU/key, sources happy/partial/all-fail,
library presence with library + wishlist + thumbs, stream effective
mode + query gen + retry, orchestrator client resolution + short
query + single source + fan-out alternates + hydrabase primary +
NDJSON drain). Full suite: 788 passing (was 694).
Ruff clean.