Яндекс: пять вечно недогружаемых карточек больше не обрывают каждый прогон добора #3574
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3574
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/yandex-perpetual-underloaded"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #3191 (issue не закрывается: в нём остаются п.4 — backfill уже сохранённых недогруженных карточек — и маркер для
newbuilding.py; это не входит в правку).Что было
PR #3364 (05.09) сделал недогруженную карточку отказом:
detail_enriched_atне ставится, объявление остаётся в очереди. Счётчика попыток на объявлении при этом не было — в комментарии 05.09 прямо записано, что вечно недогружаемая карточка «ограничена только брейкером прогона».С 13.09 21:14 этот риск сработал. Пять объявлений — 10776456, 10775964, 10775945, 10775747, 10775594 (все
scraped_at12.09 15:02, в очереди стоят подряд,is_active=t,detail_enriched_atNULL) — в каждом прогоне приходили страницей ~381 КБ безencryptedPhones/redirectPhones. Пять недогрузов подряд выбивали брейкерconsecutive_none=5.Улики (Loki
tradein-scraper+scrape_runs, прод, 17.09):attempted=5 incomplete=5на этих пятиlisting_id: 6972, 6982, 6997, 7016, 7040, 7053, 7064, 7129, 7149, 7158, 7167, 7188, 7198, 7212, 7228, 7259; ещё 7109 — 4 недогруза + таймаут на пятом.incomplete=5, и дальше очередь не двигалась. За пятёркой — 20 501 необогащённое yandex-объявление, впереди неё сейчас всего 35. Значит, ближайший прогон снова в неё упрётся./offer/5601896548455123200/,/offer/67398737598609920,/offer/7338505269989347072→ HTTP 200, 380–381 КБ, пустая SPA-оболочка: нетINITIAL_STATE, id оффера в странице не встречается ни разу. Для сравнения, обогащённый тем же утром/offer/1553505215059041024/— 3,04 МБ, 54encryptedPhones. Выходит, дело в самом объявлении, а не в сети или узле. С 12.09 свип их больше не видел (last_seen_at=scraped_at).Причина роста failed у yandex_detail_backfill с 14.09
Разобрал все прогоны 12.09–17.09 по warning-логу. Причин две:
curl: (28) Operation timed out after 30000 ms with 45–569 КБ received) — отдельный класс, и появился он раньше пятёрки: 6790, 6808, 6870, 6891 (12–13.09), потом 7087, 7250, 7298, 7307. Последние два упавших прогона (16.09 21:19 и 17.09 00:19) — чистые таймауты на других объявлениях. В этом PR таймауты не правятся: неизвестно, поможет ли больший таймаут, если узел отдаёт 3-мегабайтную страницу медленно. Нужен отдельный разбор.Что сделано
listings.detail_incomplete_count smallint NOT NULL DEFAULT 0иdetail_incomplete_at timestamptz. ADD COLUMN с константным DEFAULT не переписывает heap. ЕстьSET LOCAL lock_timeout = '5s', повторный прогон ничего не ломает (idempotent). Существующие строки не меняются.app/tasks/yandex_detail_backfill.py:count + 1иat = now(), запись коммитится сразу. Если запись упала — rollback и warning, карточка просто вернётся без паузы;incomplete_given_up: сколько необогащённых объявлений вышло из очереди после трёх недогрузов. Выбывшие не пропадают из виду.Тесты
tests/test_3191_yandex_perpetual_underloaded.py:attempted=8 enriched=3 incomplete=5, три следующие запрошены); пять первых недогрузов подряд по-прежнему обрывают его (attempted=5, следующие не запрошены);incomplete_given_up >= 5, в БДdetail_incomplete_count = [3,3,3,3,3,0,0,0]. В CI (ci-tradein.yml, Postgres) тест выполняется, локально без БД пропускается и объявлен вskip_allowlist.txt.DATABASE_URL=…localhost:5432/test pytest tests/), до rebase: 6234 passed, 45 skipped, rc=0. После rebase на свежий main: 6372 passed, 4 failed, 45 skipped, rc=1. Все 4 падения —tests/test_3466_corridor_tier_a.py(2) иtests/test_estimator_radius_floor.py(2) сAttributeError: 'Settings' object has no attribute 'estimate_corridor_clamp_*'. На чистомorigin/maina130303cони падают так же (4 failed), значит, это не эта ветка: судя по всему, #3554 и #3556 разошлись при мерже.data/sql, как в CI), до rebase: 6278 passed, 1 skipped, rc=0. После rebase 6 затронутых файлов — 35 passed, rc=0.scripts/check-migration-lock-timeout.py— rc=0.tests/test_migration_numbering.py— 3 passed.ruff check app tests— чисто.ruff format --checkна изменённых файлах — чисто.Фальсификация (живой Postgres, исходник восстановлен из копии,
diff -qпусто)1 failed, 2 passed:AssertionError: недогруженные час назад карточки снова в снапшоте — прогон опять упрётся в них, как 16 прогонов 13.09–16.092 failed, 1 passed:AssertionError: запрошено 5 из 8: повторный недогруз известных карточек оборвал прогон раньше, чем очередь дошла до следующихиAssertionError: повтор известных карточек оборвал прогон1 failed: та же ошибка «недогруженные час назад карточки снова в снапшоте…»1 failed:AssertionError: после трёх недогрузов карточка всё ещё в очередиДеплой
Миграция 321 применяется до пересоздания контейнеров; старый код новые колонки не читает. Пересоздаются
tradein-backend,tradein-scraperиtradein-tgbot.yandex_detail_backfillстартует каждые 3 ч около :19 и идёт до часа, поэтому перед деплоем проверитьSELECT id, source FROM scrape_runs WHERE status='running'.Приёмка на проде (критерий записан до факта, проверить до 21.09.2026)
_schema_migrationsсодержит321_listings_detail_incomplete_attempts.sql, уlistingsобе колонки.yandex_detail_backfill, дошедший до пятёрки, ещё может закончитьсяattempted=5 incomplete=5: у карточек пока 0 попыток, это первый недогруз. После негоSELECT id, detail_incomplete_count, detail_incomplete_at FROM listings WHERE id IN (10776456,10775964,10775945,10775747,10775594)→ у всех1.listing_id,attempted > 5(кроме обрывов по таймаутам, это второй класс).SELECT id, counters FROM scrape_runs WHERE source='yandex_detail_backfill' ORDER BY id DESC LIMIT 10.ABORT, в логепопытка 2/3,попытка 3/3. После третьей попыткиcounters.incomplete_given_up >= 5, и прогонов видаattempted=5 incomplete=5нет.attempted=5 incomplete=5на тех же id — правка не сработала.🤖 Generated with Claude Code