diff --git a/alembic/versions/20260930_0051_movies_tpdb_checked_at.py b/alembic/versions/20260930_0051_movies_tpdb_checked_at.py new file mode 100644 index 0000000..0491de2 --- /dev/null +++ b/alembic/versions/20260930_0051_movies_tpdb_checked_at.py @@ -0,0 +1,33 @@ +"""movies.tpdb_checked_at: kiedy film ostatnio szukano w TPDB (kolejka wzbogacania). + +Wzbogacanie filmow z TPDB (co 6 h po 200) bralo zawsze 200 NAJNOWSZYCH kandydatow i nie +pamietalo, ktore juz sprawdzilo. Przebieg o 05:00, po dziennym ingescie, wzbogacal 14-19 +nowych filmow, a trzy kolejne mielily te same 200 bez trafienia i konczyly z zerem. +12,9 tys. kandydatow starszych niz miesiac nie doczekalo sie ani jednego sprawdzenia +(pomiar 2026-09-30). Z data sprawdzenia kolejka idzie od niesprawdzonych, a film bez +trafienia wraca najwczesniej po 30 dniach. + +Kolumna nullable bez DEFAULT, ALTER natychmiastowy; NULL = jeszcze nie sprawdzany. + +Revision ID: 0051_movies_tpdb_checked_at +Revises: 0050_tag_vertical_counts_no_fk +Create Date: 2026-09-30 +""" +from __future__ import annotations + +from alembic import op + +revision = "0051_movies_tpdb_checked_at" +down_revision: str | None = "0050_tag_vertical_counts_no_fk" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.execute("SET LOCAL lock_timeout = '5s'") + op.execute("ALTER TABLE movies ADD COLUMN IF NOT EXISTS tpdb_checked_at timestamptz") + + +def downgrade() -> None: + op.execute("SET LOCAL lock_timeout = '5s'") + op.execute("ALTER TABLE movies DROP COLUMN IF EXISTS tpdb_checked_at") diff --git a/app/enrich/tpdb_movies.py b/app/enrich/tpdb_movies.py index 0f343c0..5aa208b 100644 --- a/app/enrich/tpdb_movies.py +++ b/app/enrich/tpdb_movies.py @@ -25,10 +25,10 @@ from __future__ import annotations import logging import uuid -from datetime import UTC, datetime +from datetime import UTC, datetime, timedelta from rapidfuzz import fuzz -from sqlalchemy import func, select +from sqlalchemy import func, select, text from sqlalchemy.orm import Session from app.connectors.tpdb import TPDBConnector, _parse_movie @@ -45,7 +45,11 @@ from app.resolve.studio_resolver import resolve_studio log = logging.getLogger(__name__) -_DASH = str.maketrans({"–": "-", "—": "-", "‑": "-"}) +# Film bez trafienia w TPDB wraca do kolejki dopiero po tym czasie (TPDB dopisuje filmy, +# wiec kiedys warto sprawdzic ponownie, ale nie cztery razy dziennie). +_RECHECK_AFTER = timedelta(days=30) + +_DASH =str.maketrans({"–": "-", "—": "-", "‑": "-"}) def _cand_year(raw: dict) -> int | None: @@ -282,7 +286,12 @@ def enrich_movie( def _candidate_movies(session: Session, *, source_id: uuid.UUID, limit: int) -> list[Movie]: """Filmy jeszcze nie wzbogacone TPDB, priorytet: mają żywy playback (są grywalne) - i brak obsady LUB brak studia (największa luka). Reszta później.""" + i brak obsady LUB brak studia (największa luka). Reszta później. + + Kolejność: najpierw nigdy nie sprawdzane (najnowsze pierwsze), potem te sprawdzone + najdawniej, ale nie wcześniej niż _RECHECK_AFTER od ostatniego razu. Bez tego każdy + przebieg brał te same 200 najnowszych bez trafienia, a starszych nie ruszał wcale + (migracja 0051).""" has_tpdb = ( select(MovieExternalRef.movie_id) .where(MovieExternalRef.source_id == source_id) @@ -307,7 +316,11 @@ def _candidate_movies(session: Session, *, source_id: uuid.UUID, limit: int) -> Movie.id.in_(has_playback), ) .where((perf_count == 0) | (Movie.studio_id.is_(None))) - .order_by(Movie.created_at.desc()) + .where( + Movie.tpdb_checked_at.is_(None) + | (Movie.tpdb_checked_at < datetime.now(UTC) - _RECHECK_AFTER) + ) + .order_by(Movie.tpdb_checked_at.asc().nulls_first(), Movie.created_at.desc()) .limit(limit) ) return list(session.execute(stmt).scalars().all()) @@ -345,6 +358,12 @@ def run_tpdb_movie_enrich( outcome = enrich_movie( session, movie, connector=connector, source_id=source_id, min_title=min_title ) + # Surowy UPDATE: nie rusza updated_at, a po merge skasowany film po prostu + # nie ma czego oznaczyc. Blad (wyjatek nizej) nie oznacza, wroci w nastepnym + # przebiegu, bo moze to byc chwilowa awaria TPDB. + session.execute( + text("UPDATE movies SET tpdb_checked_at = now() WHERE id = :id"), {"id": mid} + ) session.commit() counters[outcome] = counters.get(outcome, 0) + 1 except Exception as e: # pragma: no cover - defensywnie, jeden film nie wywala batcha diff --git a/app/models/movie.py b/app/models/movie.py index 9f28d5f..a453bd0 100644 --- a/app/models/movie.py +++ b/app/models/movie.py @@ -46,6 +46,9 @@ class Movie(UUIDPKMixin, TimestampMixin, Base): poster_url: Mapped[str | None] = mapped_column(String(2048)) backdrop_url: Mapped[str | None] = mapped_column(String(2048)) rating: Mapped[float | None] = mapped_column(Float) + # Ostatnie szukanie w TPDB (app/enrich/tpdb_movies.py), NULL = jeszcze nie. Kolejka + # wzbogacania idzie od niesprawdzonych, bez trafienia wraca po 30 dniach (migracja 0051). + tpdb_checked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) class MovieExternalRef(Base):