fix(scenes): sceny o identycznym tytule zawsze w puli kandydatow
Some checks are pending
Backend tests / test (push) Waiting to run

find_blocking_candidates OR-owal dokladny tytul z blokiem studio/data pod
jednym LIMIT 50 bez kolejnosci. Samo okno dat to ok. 45 tys. scen, wiec
scena o identycznym tytule trafiala do puli w 17% przypadkow (probka 120).
Teraz tytul idzie osobnym zapytaniem po indeksie, a blok studio+data od
najblizszej daty. Sredni czas spadl z 12 do 4 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
goon-foss 2026-10-16 11:32:37 +02:00
parent e0f70f2574
commit b613ac6827

View file

@ -4,7 +4,7 @@ from __future__ import annotations
import uuid
from datetime import date, timedelta
from sqlalchemy import and_, or_, select, text
from sqlalchemy import and_, func, select, text
from sqlalchemy.orm import Session
from app.config import get_settings
@ -165,12 +165,29 @@ def find_blocking_candidates(
- jeśli mamy studio + date → studio_id == X AND date BETWEEN ±window_days
- jeśli mamy tylko date → date BETWEEN ±window_days
- jeśli mamy tylko studio → studio_id == X
- dodatkowo, jeśli `title_normalized` podany, OR-uj exact title match
(przydaje się gdy date/studio brakuje)
- dodatkowo, jeśli `title_normalized` podany, sceny o identycznym tytule
Sceny o identycznym tytule ida osobnym zapytaniem i zawsze trafiaja do puli. Do
2026-10-16 byly OR-owane z blokiem pod jednym LIMIT bez kolejnosci, a samo okno dat
to ok. 45 tys. scen, wiec dokladny duplikat potrafil wypasc (ten sam blad co przy
filmach, find_movie_candidates). Blok studio+data idzie od najblizszej daty (12 ms
dla najwiekszego studia); kolejnosc po podobienstwie tytulu kosztowala 0,4-3 s na
scene, za drogo na ingest.
"""
if window_days is None:
window_days = get_settings().date_window_days
out: list[Scene] = []
if title_normalized:
out = list(
session.execute(
select(Scene)
.where(Scene.title_normalized == title_normalized)
.order_by(Scene.created_at.desc())
.limit(limit)
).scalars().all()
)
conds = []
if studio_id is not None and release_date is not None:
conds.append(
@ -191,11 +208,15 @@ def find_blocking_candidates(
elif studio_id is not None:
conds.append(Scene.studio_id == studio_id)
if title_normalized:
conds.append(Scene.title_normalized == title_normalized)
if not conds:
return []
return out
stmt = select(Scene).where(or_(*conds)).limit(limit)
return list(session.execute(stmt).scalars().all())
stmt = select(Scene).where(*conds)
if studio_id is not None and release_date is not None:
stmt = stmt.order_by(func.abs(Scene.release_date - release_date))
seen = {s.id for s in out}
for s in session.execute(stmt.limit(limit)).scalars().all():
if s.id not in seen:
seen.add(s.id)
out.append(s)
return out