diff --git a/app/api/scenes.py b/app/api/scenes.py index 54f7a4a..d5bbde5 100644 --- a/app/api/scenes.py +++ b/app/api/scenes.py @@ -383,13 +383,21 @@ def list_scenes( base = base.where(~live_playback_exists()) if origin: - # Substring match na origin, 'hqporner' złapie 'tube:hqpornercom'. + # Pelny origin z ekranu strony ('tube:hdporngg') porownujemy wprost: rownosc idzie + # po ix_playback_sources_origin_live, a ILIKE '%...%' przeszukiwal kazde zrodlo + # kazdej kandydujacej sceny (wyszukiwanie w obrebie strony 4,6 s, Sentry Slow DB + # Query 2026-09-15). Krotka forma z filtra ('hqporner') zostaje substringiem. + origin_clause = ( + PlaybackSource.origin == origin + if ":" in origin + else PlaybackSource.origin.ilike(f"%{origin}%") + ) base = base.where( exists( select(1).where( PlaybackSource.scene_id == Scene.id, PlaybackSource.dead_at.is_(None), - PlaybackSource.origin.ilike(f"%{origin}%"), + origin_clause, ) ) ) diff --git a/app/api/watch.py b/app/api/watch.py index 94ec34c..6395d63 100644 --- a/app/api/watch.py +++ b/app/api/watch.py @@ -20,7 +20,7 @@ from sqlalchemy import desc, select from sqlalchemy.orm import Session from app.api.device import get_device_id -from app.api.scenes import _build_scene_out +from app.api.scenes import _build_scenes_out_batch from app.api.schemas import SceneOut from app.auth import require_api_key from app.db import get_session @@ -237,11 +237,20 @@ def list_recent( if not include_finished: stmt = stmt.where(ScenePlayProgress.finished.is_(False)) + # Serializacja wsadowa jak w liscie scen: rail „Continue watching" leci przy kazdym + # starcie apki, a pelny `_build_scene_out` robil 5-7 zapytan na scene (N+1 w Sentry, + # 2026-09-14). Rail uzywa tytulu, miniatury i dlugosci, wiec wersja lekka wystarcza. + rows = session.execute(stmt).all() + outs = _build_scenes_out_batch(session, [scene for _, scene in rows], light=True, device_id=device_id) + out_by_id = {o.id: o for o in outs} items: list[WatchEntry] = [] - for prog, scene in session.execute(stmt).all(): + for prog, scene in rows: + scene_out = out_by_id.get(scene.id) + if scene_out is None: + continue items.append( WatchEntry( - scene=_build_scene_out(session, scene, device_id=device_id), + scene=scene_out, position_sec=prog.position_sec, duration_sec=prog.duration_sec, finished=prog.finished,