* fix(playback): stop seek-restart churn and premature paused-session reaping
Two latent defects (present since the initial migration) explain the
cross-client freezes on resume-after-pause, intro-skip, and manual seek
reported in #243:
1. Dueling transcode restarts. TranscodeSession.Restart had no
concurrency guard, and SegmentRecoveryDecision told concurrent
segment requests to restart again while a restart was already in
flight (the restart window runs with running=false, so requests hit
the restart-happy transcode_not_running branch before the Restarting
check). Pipelined HLS segment requests therefore spawned restarts
that kept killing the ffmpeg the player was waiting on — a 30s stall
and another restart, surfacing as buffer-then-freeze. Restart is now
single-flight and the recovery decision waits out an in-flight
restart (WaitForSegment already polls politely through one).
2. Paused sessions were reaped after 2 minutes, killing the transcode
with no revival path — every resume request then 404s. Clients that
stop progress reporting while paused (tvOS; backgrounded web tabs)
froze on play after a >5 minute pause. Paused grace is now 30
minutes in both the in-memory session manager and the DB session
cleaner.
Also unifies post-restart re-arming: the throttler and exit monitor are
re-armed via a restart hook installed at session creation and fired by
Restart itself, so the jellycompat seek path (which previously re-armed
nothing) and the audio-switch path (which re-armed only the throttler)
now behave identically to web segment recovery.
Follow-up (not in this PR): lazily revive a reaped session's transcode
on resume instead of 404ing, so even multi-hour pauses recover.
Fixes#243
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(playback): scope the restart-hook comment to handler-created sessions
The comment above SetRestartHook claimed the hook covers restarts from
'jellycompat seek', but jellycompat creates its own TranscodeSessions via
playback.StartTranscode in a separate registry and calls Restart directly;
those sessions never get the hook and never had throttler/exit-monitor
wiring to re-arm. Reword the comment (and the matching test comment) to
scope the guarantee to handler-created sessions.
Also fix TestRestartInvokesRestartHook to resolve `true` via PATH instead
of hardcoding /bin/true, which does not exist on macOS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Quick <31828688+Quick104@users.noreply.github.com>