fix(movies): kolejka wzbogacania z TPDB pamieta, co juz sprawdzila
Zadanie (co 6 h po 200) bralo zawsze 200 najnowszych kandydatow. Przebieg o 05:00 wzbogacal 14-19 swiezych filmow, trzy kolejne mielily te same 200 bez trafienia z wynikiem zero, a 12,9 tys. starszych kandydatow nie bylo sprawdzonych ani razu. Teraz movies.tpdb_checked_at (migracja 0051): najpierw niesprawdzone, film bez trafienia wraca po 30 dniach, blad nie oznacza. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cfe72195ed
commit
27309d24f2
3 changed files with 60 additions and 5 deletions
33
alembic/versions/20260930_0051_movies_tpdb_checked_at.py
Normal file
33
alembic/versions/20260930_0051_movies_tpdb_checked_at.py
Normal file
|
|
@ -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")
|
||||
|
|
@ -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,6 +45,10 @@ from app.resolve.studio_resolver import resolve_studio
|
|||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# 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({"–": "-", "—": "-", "‑": "-"})
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue