goon/alembic/versions/20260919_0044_playback_eporner_thumb_idx.py
goon-foss 41ad7f1818 feat: automatyczne sprzatanie martwych zrodel sxyprn i eporner
Oba serwisy kasuja filmy po cichu: strona odpowiada 200 z "Post Not Found" albo "Video has
been deleted". Probka 2026-09-19: 57% zywych w bazie zrodel sxyprn w wieku 10-40 dni i 22%
eporner bylo juz usunietych; w apce to puste kafelki i "the tube removed" po kliknieciu.

- eporner: ekstraktor rozpoznaje usunieta strone i rzuca HosterDead, wiec resolve oznacza
  zrodlo zamiast oddawac "blad chwilowy" (82 takie wejscia w 48 h, nic nie oznaczal).
- proxy miniatur: "Post Not Found" na sxyprn oznacza zrodlo od razu, 404 na miniaturze
  eporner uruchamia w tle sprawdzenie strony (28/30 takich miniatur to usuniete filmy).
  Indeks hash po thumbnail_url tylko dla eporner (0044), zeby znalezc zrodlo po obrazku.
- job dead-reap co 6 h: po 1500 zywych zrodel na serwis, polowa z ostatnich 30 dni.
  Oznacza tylko przy pewnym sygnale; siec i timeouty zostawia.

Sprawdzone na produkcji: 10/10 miniatur eporner i 23/23 postow sxyprn oznaczone, 17 zywych
postow nietknietych.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00

37 lines
1.3 KiB
Python

"""Indeks do szukania zrodla eporner po adresie miniatury (app/dead_sources.py).
Proxy miniatur dostaje od CDN-u eporner 404 i zna tylko adres obrazka; zeby sprawdzic i
oznaczyc film, trzeba znalezc jego zrodlo. Miniatura ma inny identyfikator niz strona
filmu, wiec bez indeksu to przeszukanie 4 mln wierszy przy kazdym pustym kafelku.
Hash i czesciowy (tylko eporner): wyszukujemy wylacznie po rownosci, a eporner to ~350 tys.
wierszy, wiec indeks ma kilkanascie MB.
CONCURRENTLY w autocommit_block, jak w 0035, 0038, 0039, 0041 i 0043.
Revision ID: 0044_playback_eporner_thumb_idx
Revises: 0043_scene_tags_tag_sort_idx
Create Date: 2026-09-19
"""
from __future__ import annotations
from alembic import op
revision = "0044_playback_eporner_thumb_idx"
down_revision: str | None = "0043_scene_tags_tag_sort_idx"
branch_labels = None
depends_on = None
def upgrade() -> None:
with op.get_context().autocommit_block():
op.execute(
"CREATE INDEX CONCURRENTLY IF NOT EXISTS ix_playback_sources_eporner_thumb "
"ON playback_sources USING hash (thumbnail_url) "
"WHERE origin = 'tube:epornercom'"
)
def downgrade() -> None:
with op.get_context().autocommit_block():
op.execute("DROP INDEX CONCURRENTLY IF EXISTS ix_playback_sources_eporner_thumb")