Commit Graph
2 Commits
Author SHA1 Message Date
gramps cc2d1ef622 TRAX: a share that is gone must never freeze the startup window
Startup took 44s and 42 of them were one line. Measured from startup.log:
OnStartup 08:42:59 -> MainWindow loaded 08:43:43, with the whole gap inside
LoadLayout, ending at

  TRAX: failed to load '\\192.168.50.86\llamaVault\Assets\Music\...':
  The network path was not found. (0x80070035)

LoadTrax called MusicPlayer.Load synchronously on the UI thread, and
new MediaFoundationReader(path) does not fail fast on a dead SMB session — it
burns the full ARP/TCP/SMB timeout and only then throws. The NAS had moved to
.87 after the power outage, so an unreachable path became a 40-second frozen
window on every launch.

The rule, from the creator: a probe may time out; a bind should return
immediately. Only one side of that is achievable here, and the reason matters —
an unreachable UNC path has no fast-fail at all, so probing it on the calling
thread is the worst possible probe. (A device open is the opposite: it normally
fails fast on a sharing violation, which is why this bug is network-specific.)

So: IsTrackReachableAsync runs the probe on a thread-pool thread under a
Task.WhenAny ceiling (TraxProbeBudget, 2s) and treats offline/missing/slow as a
normal state rather than an error. Only a probe that passed gets the real bind,
and that bind deliberately stays on the UI thread alongside every other
MusicPlayer mutation — moving the whole load off-thread would have introduced a
race against PlayTrax/PauseTrax that does not exist today. The orphan probe
thread stays parked until SMB gives up; it is not the thread anyone waits on.

One test, per the Good Dog rule: TraxProbeTests.
AHangingProbeIsAbandonedAtTheBudget_AndReportsOffline stands in a probe that
never returns and asserts the caller is released and told "offline". Drop the
ceiling and it fails on elapsed time — which is the frozen window returning.

Suite 381/381, 0 warnings.
2026-10-04 09:24:12 -07:00
gramps 535a50192c refactor: split Trax out of MainViewModel — Commit 7/12
MainViewModel.Trax.cs: music-player state (_musicPlayer/_music/_musicPlaying,
TraxIdleBrush), TRAX UI (IsMusicPlaying/TraxError/TraxDotBrush/TraxToolTip),
interaction (TraxLeftClick/TraxRightClick/PickTraxTrack), playback
(LoadTrax/PlayTrax/PauseTrax/OnTraxPlaybackEnded/RefreshTraxUi), local
loopback ducking (UpdateTraxLocalGain).

Core keeps the ctor event hookup, LoadLayout/Shutdown/SaveLayoutNow call
sites, and Scenes partial's hotkey dispatch.

Verify: 0 warnings, 246 passed, 2 known failures only.
2026-08-30 08:24:22 -07:00