fix(r5): address the seventh /code-review high round — 7 findings
Five of them sit where round 6 turned F from a Fullscreen API call into a CSS maximise: the guards around it still asked `isFullscreen`, which that pivot made permanently false. - Arrow-key volume was dead in the maximised view: the scroll-deference checked only `isFullscreenRef`, so the (now hidden but still scrollable) card kept swallowing Up/Down. Both flags now count as "the video fills the screen". Measured: 87px of scroll room on the focused card, ArrowDown moves 80 -> 75 and scrolls nothing. - The maximised view had no way out once the pointer touched the video. Reaching YouTube's controls means clicking into the cross-origin iframe, which takes keyboard focus with it, and the re-arm paths (stage mouseleave, window focus) need the pointer to leave the browser entirely while the stage fills it. So the exit now lives on screen, in our DOM: a button that un-maximises AND pulls focus back, re-arming every shortcut. - WebKit fires only `webkitfullscreenchange`/`webkitFullscreenElement`, so on Safari/iPadOS YouTube's own fullscreen never registered — no overlay yield, no focus reclaim. One `fullscreenEl()` reader, both event spellings. - The stage claimed `z-index: 9999`, the glass tuner's reserved level, for a job that only needs to beat the modal chrome it is nested in (its siblings top out at z-menu). Dropped to rail-level; nothing escapes the modal's stacking context either way. - `inset: 0` already sizes a fixed layer — the inherited `100vw`/`100vh` over-constrained it, which is how a classic scrollbar gets a horizontal overflow and a mobile URL bar hides the bottom edge (YouTube's control bar). - The shortcut hint still promised "F: fullscreen" in both locales. Backend, both "the fix stopped one layer short": - The startup HLS sweep was awaited inside lifespan, so uvicorn still served nothing until it finished — a thread doesn't help when nothing is listening yet. Fire-and-forget task instead, cancelled on shutdown. Measured with 200 planted segments: "Application startup complete" now precedes "swept 1". - An RSS poll where every channel failed returned normally, so the scheduler recorded `ok` with the outage buried in the summary string. `failed == total` now raises: a run that reached nothing is a failed run. Suites: backend 147 -> 150.
This commit is contained in:
+22
-6
@@ -70,20 +70,36 @@ async def lifespan(app: FastAPI):
|
||||
url,
|
||||
)
|
||||
# No HLS session survives a restart (they live in this process), so anything still on disk is
|
||||
# a crashed run's segments — sweep them or they accumulate forever. Off the event loop: the
|
||||
# first sweep after a long uptime can be gigabytes of `.ts` files, and blocking here delays
|
||||
# serving (a 502 + a failed post-deploy health probe).
|
||||
swept = await asyncio.to_thread(plex_stream.sweep_orphans)
|
||||
if swept:
|
||||
log.info("swept %d orphaned HLS segment directories", swept)
|
||||
# a crashed run's segments — sweep them or they accumulate forever. FIRE AND FORGET, not
|
||||
# awaited: uvicorn does not serve a single request until lifespan startup returns, so awaiting
|
||||
# the sweep would hold the port shut for as long as the rmtree runs (gigabytes of `.ts` after a
|
||||
# long uptime) — the 502 + failed post-deploy health probe this is meant to avoid. A thread
|
||||
# alone doesn't buy that; not waiting does. The sweep only touches directories no live session
|
||||
# owns, so racing it against early playback is safe.
|
||||
sweep = asyncio.create_task(_sweep_hls_orphans())
|
||||
start_scheduler()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
log.info("Siftlode shutting down")
|
||||
sweep.cancel()
|
||||
shutdown_scheduler()
|
||||
|
||||
|
||||
async def _sweep_hls_orphans() -> None:
|
||||
"""Background half of the startup HLS sweep (see lifespan). Owns its own errors: a failure here
|
||||
must never take the app down, and a cancelled shutdown is not one."""
|
||||
try:
|
||||
swept = await asyncio.to_thread(plex_stream.sweep_orphans)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except Exception:
|
||||
log.exception("HLS orphan sweep failed")
|
||||
return
|
||||
if swept:
|
||||
log.info("swept %d orphaned HLS segment directories", swept)
|
||||
|
||||
|
||||
app = FastAPI(title=settings.app_name, lifespan=lifespan)
|
||||
|
||||
app.add_middleware(
|
||||
|
||||
Reference in New Issue
Block a user