Commit graph

4 commits

Author SHA1 Message Date
BoulderBadgeDad
bacc528ba1 video search: stop slskd searches when done → fixes movie-search flooding
bug: start_search tells slskd to keep searching its full timeout (~60s), but
_search_for_retry only polled then walked away — never stopping the search. for
movies (popular → 12+ hits in <1s → worker early-breaks → fires the next search
immediately) this piled up dozens of 60s-long slskd searches at once. tv episodes
return fewer hits → workers block the full 22s → searches issue slowly → no pileup
(why tv looked fine and movies flooded).

fix: stop_search(id) (DELETE /api/v0/searches/{id}); _search_for_retry stops its
search in a finally, even on early break. concurrent slskd searches now ≈ the
worker pool (3). retry worker benefits too. tested.
2026-06-26 09:10:15 -07:00
BoulderBadgeDad
5661ccbfd2 video search: poll the FULL slskd timeout (~60s) + explain audio-only results
The poll capped at 32s but slskd results trickle in over ~50s (the music side waits
the whole search_timeout), so slow searches like 'Project Hail Mary' returned 'none'
before results landed. Now:
- /search/start returns poll_ms (slskd search_timeout + 8s); the UI polls that long
  (capped 80s), streaming results as they arrive, stopping early only once results
  clearly plateau (≥20s + stable) or hit 25.
- /search/poll returns total_files; when 0 video releases but slskd DID return files,
  the panel says 'returned N files, but none are video — likely audio/other for this
  title' instead of a blank 'none' (Soulseek is audio-heavy; many movie titles are
  audiobooks there). slskd_search.poll_search() returns {hits, total_files}.
Tests green, ruff + balance clean.
2026-06-19 16:55:53 -07:00
BoulderBadgeDad
42c67a6d4d video search: stream slskd results (start + poll) — fixes 'no results'
The old search did a 4.5s slskd search + 8s wait; slskd responses trickle in over
10-30s, so the window closed before results arrived (you'd see them in slskd but the
panel said none). Now it works like the music side:
- slskd_search.start_search() (uses the shared soulseek.search_timeout) + poll_responses().
- POST /downloads/search/start (mock = immediate; soulseek = returns a search id) +
  GET /downloads/search/poll. Shared _evaluate_hits ranks each poll's hits.
- UI streams: starts the search, polls every 1.3s, renders results live with a
  'searching…' badge, stops when results plateau (4 stable polls) or ~32s. Live
  re-renders suppress per-card entrance so it doesn't blink.
Tests green, ruff clean.
2026-06-19 15:23:47 -07:00
BoulderBadgeDad
305020f61e video search: REAL slskd search for the Soulseek source (was mocked)
The Soulseek ⌕ now actually queries your slskd instance instead of fabricating
results. core/video/slskd_search.py (isolated): build_query(scope,…) → POST
/api/v0/searches (shared soulseek.* URL+key) → poll /responses (bounded ~8s,
early-exit at 25) → keep video files → group_video_files() folds them into one hit
per release folder with a peer count + the fastest available source. Same
{title,size_bytes,…} shape, so parse→evaluate→rank/cards are unchanged.

Endpoint routes source=='soulseek' to slskd (torrent/usenet stay mocked), surfaces
'slskd not configured' / network errors, carries username/peers/slots/filename
through for the cards + a future real Grab, and caps to 40. Pure helpers tested (4);
isolation guard + ruff clean.
2026-06-19 14:16:44 -07:00