fix(scraper-kit): yandex _leaf под CAP не пишется в done-леджер как complete — capped_buckets отдельным счётчиком #3373

Merged
bot-backend merged 2 commits from fix/3368-yandex-leaf-complete-flag into main 2026-09-05 20:22:50 +00:00

2 commits

Author SHA1 Message Date
9519c89d92 fix(scraper-kit/yandex): выпавшая страница leaf'а делает бакет неполным; capped_buckets переживает дрейн
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 12s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m5s
Ревью #3373, два minor:
1. `_leaf` считал полноту только по потолку страниц — упавшая страница
   (`payload=None` → `[]`) молча уходила в чекпоинт как собранная. Теперь
   паритет с cian по-настоящему: `complete = not capped and dropped_pages == 0`.
2. `counters.capped_buckets` присваивался ПОСЛЕ await — cancel/shutdown
   (RuntimeError из `_on_bucket`) уносил управление мимо строки. Перенесено в
   `finally`, счётчик виден в финальном payload дрейна.

Нит: `ceil(total / 20)` → `_GATE_PAGE_SIZE`.

Тесты по значению: бакет с 1 выпавшей страницей из 3 — не в done-леджере
(+ контроль: 3 успешных страницы по-прежнему complete); дрейн после обрезанного
бакета → `capped_buckets == 1` в финальных counters. Фейк `_DrainAtFirstBucket`
(#3355) теперь объявляет `capped_buckets` явно: его catch-all `__getattr__`
отдавал корутину на любое имя и ронял сериализацию counters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 01:16:14 +05:00
5ad0d1a304 fix(scraper-kit/yandex): обрезанный потолком страниц leaf не идёт в чекпоинт
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m54s
После #3362 degraded-ветка отмечается complete=False, а `_leaf` писал бакет как
полный, даже когда его пагинация упиралась в max_pages_per_bucket/_GATE_MAX_PAGES_CAP.
С containment-гейтом (#3358/#3359) такой ключ покрывает свой интервал целиком, и
резюм больше не заходит в полосу, чей хвост не читали ни разу.

Флаг полноты — как у cian: complete = pages_needed <= max_pages, передаётся в
on_bucket на обоих выходах leaf'а (_mark_bucket кладёт в done только complete).
Переполненный leaf возможен только там, где бисекции дробить нечем (размах <
min_bracket, открытый верхний брекет, потолок глубины) — это честный исход
«бакет неполон по построению», поэтому он ещё и считается отдельно
(scraper.capped_buckets → counters.capped_buckets): лечится не повтором прогона,
а порогами бисекции.

Closes #3368
2026-09-06 00:56:36 +05:00