fix(api): progress checkpoints past the int4 column are a 422, and idle HLS sessions are reaped on a timer
Deep-review round 3 of bug hunt 2026-09. - The YouTube and Plex progress bodies are bounded by POSITION_MAX_S (the int4 position columns): a finite position of 2^31 or more was a DataError, i.e. a 500 — the sibling of round 2's non-finite fix. - plex/stream.py promised "a periodic reaper", but reap_idle ran only inside the NEXT session request: after the last playback an abandoned session (its ffmpeg still working, its directory a whole segmented copy of the film) lived until someone pressed play again. A lifespan task reaps every 60 s. - Tests for what round 2 left untested: the 422's body keeps the list shape the UI localizes, and stream_session refuses non-finite start/aoff.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
"""Idle HLS sessions are reaped on a timer, not only when the next session is requested.
|
||||
|
||||
plex/stream.py promises "a periodic reaper kills idle ones", but `reap_idle` ran only inside
|
||||
POST /session: after the last playback, an abandoned session (its ffmpeg still working through the
|
||||
film, its directory a whole segmented copy of it) lived until somebody pressed play again.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
import app.main as app_main
|
||||
from app.main import app
|
||||
|
||||
|
||||
class _Configured:
|
||||
def __enter__(self):
|
||||
return None
|
||||
|
||||
def __exit__(self, *exc):
|
||||
return False
|
||||
|
||||
|
||||
def test_idle_sessions_are_reaped_while_nobody_starts_a_new_one(monkeypatch):
|
||||
async def _no_sweep():
|
||||
return None
|
||||
|
||||
reaped: list[int] = []
|
||||
monkeypatch.setattr(app_main, "SessionLocal", _Configured)
|
||||
monkeypatch.setattr(app_main.state, "is_configured", lambda db: True)
|
||||
monkeypatch.setattr(app_main, "_sweep_hls_orphans", _no_sweep)
|
||||
monkeypatch.setattr(app_main, "start_scheduler", lambda: None)
|
||||
monkeypatch.setattr(app_main, "shutdown_scheduler", lambda: None)
|
||||
monkeypatch.setattr(app_main.plex_subtitles, "shutdown", lambda: None)
|
||||
monkeypatch.setattr(app_main, "_HLS_REAP_EVERY_S", 0.01)
|
||||
monkeypatch.setattr(app_main.plex_stream, "reap_idle", lambda: reaped.append(1) or 0)
|
||||
|
||||
async def _cycle():
|
||||
async with app_main.lifespan(app):
|
||||
await asyncio.sleep(0.2)
|
||||
|
||||
asyncio.run(_cycle())
|
||||
assert len(reaped) >= 2, "no periodic reap ran while the app was up"
|
||||
Reference in New Issue
Block a user