soulsync/webui/static
Broque Thomas df675c7c9f Fix: Usenet bundle stuck on "downloading release" when SAB History flips before storage lands (#721)
Follow-up to the 2.6.3 queue→history handoff fix (#706). User
@IamGroot60 reported in #721 that on 2.6.3 the bundle still gets
stuck mid-flight: SoulSync UI sits on "Usenet downloading release
61%" forever, SAB History shows the job as Completed 2+ minutes
ago, files are physically present in the slskd downloads folder
but never copied into ``storage/album_bundle_staging/<batch>/``.

Root cause: a second-stage gap in the SAB pipeline. SAB flips a
job's ``status`` to ``Completed`` in History as soon as par2 +
unrar finish, but its post-processing pipeline writes the final
``storage`` field a few seconds LATER (the move-to-final step).
``poll_album_download`` saw the first ``Completed`` read with
``save_path=None`` and bailed:

  if status.state in complete_states:
      return last_save_path  # ← None at this point

``download_album_to_staging`` got ``save_path=None``, set
``result['error']`` and returned. The bundle was marked failed but
the LAST progress emit before the failure was ``downloading
progress=0.61``, so the UI froze on "61%" — the terminal ``failed``
emit never registered on the user's screen because the renderer
holds the last-known progress.

Fix
- ``poll_album_download`` now tracks a separate transient counter
  for "complete state seen, save_path not yet set." Up to
  ``transient_miss_threshold`` (default 5) consecutive reads in
  that state are tolerated before the poll bails. SAB writes the
  ``storage`` field within 2-10 seconds of the History flip in
  practice — the default 5 × 2s = 10s window covers it.
- When save_path eventually lands, return it normally.
- When the threshold is exhausted with save_path still empty,
  emit terminal ``failed`` with an explicit message pointing at
  the missing save_path field — no more 6-hour silent spin.
- Earlier ``downloading`` reads with a non-empty ``save_path``
  (qBit / Transmission set this from the start of the download)
  remain "sticky" — if the eventual ``completed`` read has empty
  save_path, the cached one applies. So torrent flows aren't
  affected by the retry path.

SAB adapter (``_parse_history_slot``)
- Widened the save_path field fallback chain:
    storage → path → download_path → dirname → incomplete_path
  Covers SAB version differences (older builds populated ``path``)
  and forks that expose ``download_path`` or ``dirname``.
  ``incomplete_path`` is the last resort — SAB's in-progress dir
  before the final move — so the bundle plugin at least has a
  path to scan when nothing else lands.
- Whitespace-only values are skipped.
- Loud debug log when none of the known fields land — users on
  SAB versions / forks with novel field names need to see this in
  logs so we can grow ``_HISTORY_SAVE_PATH_KEYS``.

Tests
- ``test_album_bundle.py`` (3 new):
  - tolerates_completed_with_late_save_path_arrival — the #721
    scenario; first Completed read has no save_path, third has
    it; poll returns the path normally
  - gives_up_when_completed_with_no_save_path_persists — past
    the threshold the poll fails loudly instead of silent-spinning
  - uses_save_path_from_earlier_downloading_emit_if_completed_lacks_one
    — sticky save_path keeps torrent flows working
- ``test_usenet_client_adapters.py`` (6 new):
  - falls back to ``path`` when ``storage`` empty
  - falls back to ``download_path``
  - prefers ``storage`` when multiple fields present
  - returns ``None`` when all fields empty (the #721 gap window)
  - ignores whitespace-only values
  - uses ``incomplete_path`` as last resort

132 album-bundle + usenet tests pass.

Branch is on dev parented at 2.6.3 — user @IamGroot60 offered
to test on dev, so this is a candidate cherry-pick for either
a 2.6.4 hotfix or merge straight into dev for the next release.
2026-05-28 08:01:52 -07:00
..
docs update docs page 2026-03-13 08:35:28 -07:00
vendor Add WebSocket real-time updates with automatic HTTP polling fallback 2026-03-03 18:26:29 -08:00
amazon.svg Wire Amazon Music enrichment worker into dashboard UI 2026-05-16 17:43:38 -07:00
api-monitor.js Dashboard: round Last.fm avatar, invert dark-mark logos (Tidal/Qobuz/Discogs/Amazon) 2026-05-27 19:32:32 -07:00
artists.png add static images 2026-03-09 17:35:46 -07:00
audiodb.png Dashboard: equalizer bars now show real brand logos in the avatar disc 2026-05-27 19:22:28 -07:00
auto-sync.js Auto-Sync sidebar: brand logo on each source-group header 2026-05-27 20:23:12 -07:00
automation.png add static images 2026-03-09 17:35:46 -07:00
beatport-ui.js Add "All Libraries (combined)" mode to PlexClient 2026-05-06 15:39:19 -07:00
core.js Persist completed downloads in downloads view 2026-05-24 10:02:00 -07:00
dashboard.png add static images 2026-03-09 17:35:46 -07:00
discover-section-controller.js Discover controller — Cin pre-review polish 2026-05-07 20:35:10 -07:00
discover.js Fix missing album placeholder asset path 2026-05-22 08:34:42 -07:00
discover.png add static images 2026-03-09 17:35:46 -07:00
docs-images-needed.md Service Badges, Page Headers, Docs Page, and Bug Fixe 2026-03-10 14:47:11 -07:00
docs.js Clean up stale Artists-page references in helper.js + docs.js 2026-04-22 20:29:32 -07:00
downloads.js Wishlist: distinguish Queued from Analyzing for executor-pending batches 2026-05-27 14:52:02 -07:00
enrichment.js Wire Amazon Music enrichment worker into dashboard UI 2026-05-16 17:43:38 -07:00
explorer.png Create explorer.png 2026-03-30 17:23:31 -07:00
favicon.png enlarge favicon 2026-02-13 16:11:32 -08:00
help.png Add media server setup, processing settings, text import, automation history, and streaming details 2026-03-10 15:35:18 -07:00
helper.js Fix: Usenet bundle stuck on "downloading release" when SAB History flips before storage lands (#721) 2026-05-28 08:01:52 -07:00
hydrabase.png Add Hydrabase dev UI and WebSocket support 2026-02-21 00:32:04 -08:00
import.png add static images 2026-03-09 17:35:46 -07:00
init.js chore(webui): remove legacy import feature js / css code 2026-05-24 21:17:19 +03:00
library.js Branch cleanup: lift manual-match helpers, fix length-pref ordering, profile-scope view toggle 2026-05-27 07:43:21 -07:00
library.png add static images 2026-03-09 17:35:46 -07:00
manifest.json Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
media-player.js Improve radio mode UI and behavior 2026-05-24 11:02:19 -07:00
mobile.css style(import): add separate styles for mobile 2026-05-24 21:17:21 +03:00
pages-extra.js Wishlist: distinguish Queued from Analyzing for executor-pending batches 2026-05-27 14:52:02 -07:00
particles.js Add particle background toggle & optimize accent color caching 2026-03-13 16:05:22 -07:00
placeholder-album.png Add missing placeholder-album.png to stop 404 spam in console 2026-03-23 18:05:11 -07:00
pwa-icon-192.png Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
pwa-icon-512.png Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
search.js fix(webui): preserve import tab refresh URLs 2026-05-24 21:17:20 +03:00
search.png add static images 2026-03-09 17:35:46 -07:00
settings.js Clarify hybrid source album behavior 2026-05-23 15:15:28 -07:00
settings.png add static images 2026-03-09 17:35:46 -07:00
setup-wizard.css Add informative help text and tips to every setup wizard step 2026-04-11 23:26:01 -07:00
setup-wizard.js Rebrand folder terminology: Download→Input, Transfer→Output, Staging→Import 2026-04-18 17:35:20 -07:00
shared-helpers.js refactor(webui): finish stats standalone handling in react 2026-05-23 23:01:56 +03:00
shell-bridge.js refactor(webui): finish stats standalone handling in react 2026-05-23 23:01:56 +03:00
stats-automations.js Merge pull request #594 from Skowll/telegram_thread_id 2026-05-26 11:47:08 -07:00
style.css Sync page: collapse tabs to brand-logo chips with active label pill 2026-05-27 22:04:28 -07:00
sw.js Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
sync-lastfm.js Add Last.fm Radio tab to Sync page (Phase 1c.2) 2026-05-26 15:24:23 -07:00
sync-listenbrainz.js Add Last.fm Radio tab to Sync page (Phase 1c.2) 2026-05-26 15:24:23 -07:00
sync-services.js Add SoulSync Discovery tab to Sync page (Phase 1c.3) 2026-05-26 19:46:03 -07:00
sync-soulsync-discovery.js SoulSync Discovery tab: open mirror detail modal after refresh 2026-05-26 20:02:50 -07:00
sync-spotify.js feat(media-player): playable tracks across modals + lyrics + cleanups 2026-05-22 21:19:50 -07:00
sync.png add static images 2026-03-09 17:35:46 -07:00
trans.png Add SoulID worker with API-based debut year disambiguation 2026-03-21 10:21:06 -07:00
trans2.png Create trans2.png 2026-03-21 10:23:36 -07:00
whisoul.png Add library repair worker and UI 2026-02-21 15:00:23 -08:00
wishlist-tools.js Merge pull request #594 from Skowll/telegram_thread_id 2026-05-26 11:47:08 -07:00
worker-orbs.js Wire Amazon Music enrichment worker into dashboard UI 2026-05-16 17:43:38 -07:00