fix(tradein/scrapers): обрыв по серии блоков рвал каждый прогон, включая здоровые #3188

Merged
bot-backend merged 1 commit from fix/3184-block-ratio-threshold into main 2026-08-28 18:22:26 +00:00
Collaborator

Суть

Все 40 прогонов avito_detail_backfill за 14 суток закончились banned. Ни один не завершился штатно. Доля блоков при этом колебалась 25-100%:

4786   125/190 обогащено, 47 блоков,  25%   banned
4878    61/100,            39,        39%   banned
4910    35/71,             33,        46%   banned
5200    43/63,             20,        32%   banned
5190     0/5,               5,       100%   banned

Прогон, честно обогативший 125 карточек из 190, получал тот же статус, что и прогон 0 из 5.

Обрывало правило «N блоков подряд». Оно не отличает выгоревший пул от здорового сбора, потому что блоки автокоррелированы и идут пачками: при базовой доле 25-46% пачка из 5-6 подряд у независимой модели была бы редкостью, а встречается в каждом прогоне. Критерий, срабатывающий всегда, не несёт информации.

Что изменено

  • BlockRatioBreaker — доля блоков в скользящем окне последних N попыток. Дефолт: окно 20, порог 0.7, оба в настройках с валидацией диапазона (ge=1, 0.0..1.0 — оператор, введший 70 вместо 0.7, получит ошибку, а не молча выключенный критерий).
  • Пачка сама по себе обрыв больше не вызывает.
  • В counters пишется гистограмма длин пачек. Без неё эффект этой и любой следующей правки измерить нечем — сегодня там только итоги.

Safety-net и почему он с условием

Старое поведение сохранено, но только для прогонов короче окна, где доля физически недостижима: 0/5 останавливается как раньше.

Без этого условия safety-net гасил бы сам фикс. Холодный старт сессии/прокси — самое вероятное место пачки, и длинный прогон обрывался бы на пятой попытке точно так же, как до правки, не дав критерию по доле включиться. Найдено ревью, исправлено.

Чего этот PR НЕ делает

Домклик не трогаем. Исходная постановка (моя) говорила «тот же критерий», но у Домклика один выделенный residential-прокси без ротации, и max_consecutive_blocks=3 у него ниже avito осознанно — data/sql/175_scrape_schedules_seed_domclick_detail_backfill.sql:41-44 объясняет: ранний обрыв бережёт репутацию единственного узла.

Наша калибровка сделана на пуле с ротацией. При устойчивой доле около 0.65 Домклик по этому критерию не оборвался бы никогда — десятки запросов по QRATOR с одного IP, ровно то, что порог 3 был призван предотвратить. Данных по Домклику у нас ноль. Своя калибровка — отдельной задачей.

Тесты

30 в файле avito, включая новые в обе стороны:

  • 47/190 (25%) и 20/63 (32%) — реальные прогоны, не обрываются;
  • пачка из 6 подряд посреди здорового прогона — не обрывает, гистограмма пишет {"6": 1};
  • сплошные блоки после первого успеха — обрыв ровно на 20-й попытке (окно заполняется двадцатым элементом);
  • граница: 14/20 обрывает (порог >=), 13/20 нет;
  • 5/5 через safety-net — как сегодня.

Test plan

  • 40 passed локально (30 avito + 10 domclick нетронуты), ruff чист
  • CI зелёный
  • После деплоя: прогон с долей блоков ниже 0.7 завершается done, а не banned
  • В counters появилась block_streak_histogram — по ней впервые можно будет измерить реальную длину пачек

Closes #3184

## Суть **Все 40 прогонов `avito_detail_backfill` за 14 суток закончились `banned`. Ни один не завершился штатно.** Доля блоков при этом колебалась 25-100%: ``` 4786 125/190 обогащено, 47 блоков, 25% banned 4878 61/100, 39, 39% banned 4910 35/71, 33, 46% banned 5200 43/63, 20, 32% banned 5190 0/5, 5, 100% banned ``` Прогон, честно обогативший 125 карточек из 190, получал тот же статус, что и прогон 0 из 5. Обрывало правило «N блоков подряд». Оно не отличает выгоревший пул от здорового сбора, потому что **блоки автокоррелированы и идут пачками**: при базовой доле 25-46% пачка из 5-6 подряд у независимой модели была бы редкостью, а встречается в каждом прогоне. Критерий, срабатывающий всегда, не несёт информации. ## Что изменено - `BlockRatioBreaker` — доля блоков в скользящем окне последних N попыток. Дефолт: окно 20, порог 0.7, оба в настройках с валидацией диапазона (`ge=1`, `0.0..1.0` — оператор, введший `70` вместо `0.7`, получит ошибку, а не молча выключенный критерий). - Пачка сама по себе обрыв больше не вызывает. - В `counters` пишется гистограмма длин пачек. Без неё эффект этой и любой следующей правки измерить нечем — сегодня там только итоги. ## Safety-net и почему он с условием Старое поведение сохранено, но **только для прогонов короче окна**, где доля физически недостижима: 0/5 останавливается как раньше. Без этого условия safety-net гасил бы сам фикс. Холодный старт сессии/прокси — самое вероятное место пачки, и длинный прогон обрывался бы на пятой попытке точно так же, как до правки, не дав критерию по доле включиться. Найдено ревью, исправлено. ## Чего этот PR НЕ делает **Домклик не трогаем.** Исходная постановка (моя) говорила «тот же критерий», но у Домклика **один выделенный residential-прокси без ротации**, и `max_consecutive_blocks=3` у него ниже avito осознанно — `data/sql/175_scrape_schedules_seed_domclick_detail_backfill.sql:41-44` объясняет: ранний обрыв бережёт репутацию единственного узла. Наша калибровка сделана на пуле **с** ротацией. При устойчивой доле около 0.65 Домклик по этому критерию не оборвался бы никогда — десятки запросов по QRATOR с одного IP, ровно то, что порог 3 был призван предотвратить. Данных по Домклику у нас ноль. Своя калибровка — отдельной задачей. ## Тесты 30 в файле avito, включая новые в обе стороны: - 47/190 (25%) и 20/63 (32%) — реальные прогоны, **не** обрываются; - пачка из 6 подряд посреди здорового прогона — не обрывает, гистограмма пишет `{"6": 1}`; - сплошные блоки после первого успеха — обрыв ровно на 20-й попытке (окно заполняется двадцатым элементом); - граница: 14/20 обрывает (порог `>=`), 13/20 нет; - 5/5 через safety-net — как сегодня. ## Test plan - [x] 40 passed локально (30 avito + 10 domclick нетронуты), ruff чист - [ ] CI зелёный - [ ] После деплоя: прогон с долей блоков ниже 0.7 завершается `done`, а не `banned` - [ ] В `counters` появилась `block_streak_histogram` — по ней впервые можно будет измерить реальную длину пачек Closes #3184
bot-backend added 1 commit 2026-08-28 18:16:20 +00:00
fix(tradein/scrapers): обрыв по серии блоков рвал каждый прогон, включая здоровые
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (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 4m50s
745f15bdb1
Все 40 прогонов avito_detail_backfill за 14 суток закончились 'banned'.
Ни один не завершился штатно. Доля блоков при этом колебалась 25-100%:
прогон, обогативший 125 карточек из 190, получал тот же статус, что и
прогон 0 из 5.

Обрывало правило "N блоков подряд". Оно не отличает выгоревший пул от
здорового сбора, потому что блоки автокоррелированы и идут пачками: при
базовой доле 25-46% пачка из 5-6 подряд у независимой модели была бы
редкостью, а встречается в каждом прогоне. Критерий, срабатывающий
всегда, не несёт информации.

Теперь абортит доля блоков в скользящем окне последних N попыток
(дефолт 20 при пороге 0.7, оба в настройках с валидацией диапазона).
Пачка сама по себе обрыв не вызывает.

Safety-net старого поведения сохранён, но только для прогонов КОРОЧЕ
окна, где доля физически недостижима: 0/5 останавливается как раньше.
Без этого условия safety-net гасил бы сам фикс -- холодный старт
сессии самое вероятное место пачки, и длинный прогон обрывался бы на
пятой попытке точно так же, как до правки.

Домклик намеренно НЕ трогаем: у него один выделенный residential-прокси
без ротации, и max_consecutive_blocks=3 у него ниже avito осознанно
(data/sql/175) -- ранний обрыв бережёт репутацию единственного узла.
Наша калибровка сделана на пуле С ротацией и туда не переносится;
своя калибровка отдельной задачей.

В counters пишется гистограмма длин пачек -- без неё эффект этой и
любой следующей правки измерить нечем: сейчас там только итоги.

Refs #3184
bot-backend merged commit 49b70a67f3 into main 2026-08-28 18:22:26 +00:00
bot-backend deleted branch fix/3184-block-ratio-threshold 2026-08-28 18:22:27 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3188
No description provided.