fix(plex): a finished HLS session outlives a throttled heartbeat
This commit is contained in:
@@ -1160,9 +1160,13 @@ def sweep_orphans(older_than: float | None = None) -> int:
|
||||
return dropped
|
||||
|
||||
|
||||
# How long a session whose ffmpeg has FINISHED may go unfetched before a new session request reaps
|
||||
# it (see reap_idle).
|
||||
_FINISHED_IDLE_S = 30
|
||||
# The slowest heartbeat a live player sends: a browser cuts the timers of a hidden page that makes no
|
||||
# sound to one a minute (measured on Chromium: a paused and a muted player, about a minute after
|
||||
# hiding; a hidden player with sound keeps its 10 s).
|
||||
_THROTTLED_HEARTBEAT_S = 60
|
||||
# How long a session whose ffmpeg has FINISHED may go without a signal before `reap_idle` takes it:
|
||||
# the beat before the reaper looks, one lost on the way, and the time the next one takes to arrive.
|
||||
_FINISHED_IDLE_S = 3 * _THROTTLED_HEARTBEAT_S
|
||||
|
||||
|
||||
def reap_idle(finished_idle_s: float = _FINISHED_IDLE_S) -> int:
|
||||
@@ -1171,15 +1175,17 @@ def reap_idle(finished_idle_s: float = _FINISHED_IDLE_S) -> int:
|
||||
|
||||
A finished session is also what a PAUSED viewer has: a remux runs far faster than realtime, so
|
||||
ffmpeg is done a minute or two in and writes ENDLIST; hls.js then stops asking for the playlist,
|
||||
and with its forward buffer full a paused player fetches nothing at all. With the 30 s rule that
|
||||
killed a one-minute pause, and playback died ~30 s after resuming.
|
||||
and with its forward buffer full a paused player fetches nothing at all.
|
||||
|
||||
What makes the short rule safe again is that fetching is no longer the only signal: a player
|
||||
parked MID-ITEM checkpoints its position every 10 s, and that route calls `touch_session`, so a
|
||||
viewer who is merely paused says so far more often than this rule asks. The heartbeat
|
||||
What makes the short rule safe is that fetching is not the only signal: a player parked MID-ITEM
|
||||
checkpoints its position and that route calls `touch_session`. That beat is every 10 s only while
|
||||
the page is visible or making sound; a hidden, silent one sends it once a minute, which a 30 s
|
||||
rule killed whenever the reaper happened to run more than 30 s after the beat (measured: a paused
|
||||
session gone that way, and one that lived on the same cadence because its phase was luckier).
|
||||
So the rule is sized to the throttled beat (`_THROTTLED_HEARTBEAT_S`). The heartbeat
|
||||
stops once the item is finished or before a position is known (`usePlexProgress.flush`) — both
|
||||
states where reaping is correct, and where the player's 404 → reclaim recovers a viewer who
|
||||
scrubs back in anyway. Do not restate this as "every 10 s whether or not it is playing":
|
||||
scrubs back in anyway. Do not restate this as "whether or not it is playing":
|
||||
a review found that claim in two comments and not in the code. An earlier blanket
|
||||
`reap_abandoned` bought the same safety by keeping every finished session for ten minutes — each
|
||||
one a whole segmented copy of the film on a volume shared with the download center."""
|
||||
|
||||
Reference in New Issue
Block a user