Обрыв по серии блоков срабатывает на КАЖДОМ прогоне (40 из 40 за 14 дней) — критерий не несёт информации #3184

Closed
opened 2026-08-28 17:34:38 +00:00 by bot-backend · 2 comments
Collaborator

Найдено замером 28.08 (подробности в #3181).

Прогон 5200 при 68% успеха (enriched=43 attempted=63 blocked=20) всё равно получил status=banned — сработал порог «N блоков подряд» (avito_detail_backfill.py, max_consecutive_blocks).

Почему это дефект

Блоки Авито стохастичны. Проверено прямо: карточка 8270330752 холодным заходом дала заглушку 5 918 б, а через несколько минут тем же режимом — полные 663 886 б. Не свойство карточки, не свойство адреса в моменте, а вероятность.

При доле блоков p=0.32 вероятность пяти подряд в конкретной позиции равна 0.32^5 = 0.0034. Позиций в прогоне из 60+ попыток — около шестидесяти. Совокупно около 18% совершенно здоровых прогонов обрываются случайной серией, объявляют себя забаненными и выбрасывают остаток очереди.

Заодно в алерт уходит утверждение о причине, которого никто не измерял (это отдельно поправлено в #3178).

Почему правило всё же нужно

На выгоревшем пуле оно работает верно: прогоны 5140-5190 давали 5 блоков из 5 попыток — там серия не случайна, и остановка правильная.

Дефект в критерии, не в самой идее останова.

Что сделать

Смотреть на долю блоков в скользящем окне, а не на длину серии:

  • останов при, скажем, >60% блоков в последних 20 попытках — отличает выгоревший пул (100%) от здорового (30%);
  • серия сама по себе останов не вызывает;
  • минимальный размер окна, чтобы короткий прогон не обрывался на первых же неудачах.

Пороги подобрать по историческим прогонам: у нас есть и заведомо выгоревшие (5140-5190, 0-2 обогащено), и заведомо здоровые (5200, 43 обогащено) — на них правило и проверить.

Приёмка

  • Прогон с 68% успеха не помечается banned
  • Прогон с 0/5 по-прежнему останавливается
  • Правило проверено на исторических прогонах обоих типов
  • Домклик — тот же критерий

Оценка S/M. Refs #3177, #3178, #3181

Найдено замером 28.08 (подробности в #3181). Прогон 5200 при **68% успеха** (`enriched=43 attempted=63 blocked=20`) всё равно получил `status=banned` — сработал порог «N блоков подряд» (`avito_detail_backfill.py`, `max_consecutive_blocks`). ## Почему это дефект Блоки Авито **стохастичны**. Проверено прямо: карточка `8270330752` холодным заходом дала заглушку 5 918 б, а через несколько минут тем же режимом — полные 663 886 б. Не свойство карточки, не свойство адреса в моменте, а вероятность. При доле блоков p=0.32 вероятность пяти подряд в конкретной позиции равна 0.32^5 = 0.0034. Позиций в прогоне из 60+ попыток — около шестидесяти. Совокупно **около 18% совершенно здоровых прогонов обрываются случайной серией**, объявляют себя забаненными и выбрасывают остаток очереди. Заодно в алерт уходит утверждение о причине, которого никто не измерял (это отдельно поправлено в #3178). ## Почему правило всё же нужно На выгоревшем пуле оно работает верно: прогоны 5140-5190 давали 5 блоков из 5 попыток — там серия не случайна, и остановка правильная. Дефект в **критерии**, не в самой идее останова. ## Что сделать Смотреть на **долю блоков в скользящем окне**, а не на длину серии: - останов при, скажем, >60% блоков в последних 20 попытках — отличает выгоревший пул (100%) от здорового (30%); - серия сама по себе останов не вызывает; - минимальный размер окна, чтобы короткий прогон не обрывался на первых же неудачах. Пороги подобрать по историческим прогонам: у нас есть и заведомо выгоревшие (5140-5190, 0-2 обогащено), и заведомо здоровые (5200, 43 обогащено) — на них правило и проверить. ## Приёмка - [ ] Прогон с 68% успеха не помечается `banned` - [ ] Прогон с 0/5 по-прежнему останавливается - [ ] Правило проверено на исторических прогонах обоих типов - [ ] Домклик — тот же критерий Оценка S/M. Refs #3177, #3178, #3181
bot-backend added the
bug
priority/p1
scope/backend
scrapers
tradein
labels 2026-08-28 17:34:39 +00:00
Author
Collaborator

История за 14 дней делает вывод сильнее, а мою оценку — неверной.

Выгрузил все прогоны avito_detail_backfill за две недели. 40 из 40 закончились banned. Ни один не завершился штатно.

Доля блоков при этом разная — от 25% до 100%:

 id    дата         обогащено/попыток  блоков  доля
4786   24.08 09:16      125/190          47     25%   banned
4878   25.08 09:18       61/100          39     39%   banned
4910   25.08 21:19       35/71           33     46%   banned
5200   28.08 16:47       43/63           20     32%   banned
4819   24.08 18:17        8/21           10     48%   banned
...
5190   28.08 13:47        0/5             5    100%   banned
5140   28.08 01:46        0/5             5    100%   banned

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

Что это значит

Правило «N блоков подряд» срабатывает на каждом прогоне без исключения. Прогон никогда не заканчивается тем, что очередь разобрана, — он всегда обрывается тripwire'ом, и разница только в том, как далеко успел уйти.

Критерий, который срабатывает всегда, не несёт информации. Он не отличает выгоревший пул от здорового, потому что говорит «забанен» в обоих случаях. Именно поэтому картина деградации выглядела как обвал: она смешивает удачу отдельного прогона с состоянием источника.

Поправка к моей предыдущей оценке

Я написал «около 18% здоровых прогонов обрываются случайной серией», посчитав вероятность как для независимых событий: 0.32^5 × число позиций. Эта арифметика верна только при независимости, а данные её опровергают — при 25-32% блоков пятёрки подряд обязаны быть редкими, но они случаются в каждом прогоне.

Значит блоки автокоррелированы: они идут пачками. Получив один блок, следующий запрос получает блок с сильно большей вероятностью — похоже на временный rate-limit, который отпускает.

Точную долю ложных срабатываний по имеющимся данным посчитать нельзя: в counters лежат только итоги, последовательности попыток нет. Но она заведомо не 18%, а близка к 100% — по факту, а не по модели.

Следствия для реализации

  1. Порог по доле в скользящем окне — как и планировалось, но пороги теперь есть на чём калибровать: выгоревшие прогоны дают 100%, здоровые — 25-48%. Граница между ними широкая, где-нибудь около 60-70%.
  2. Пачечность надо учесть явно. Окно должно быть заметно длиннее типичной пачки, иначе оно повторит дефект серии. Раз пачки длиной ≥5 встречаются в каждом прогоне, окно от 20 попыток.
  3. Логировать последовательность исходов (хотя бы сжато, в counters) — сейчас нечем измерить ни длину пачек, ни эффект любой будущей правки. Без этого следующий разбор снова упрётся в «есть только итоги».
  4. Пересмотреть, что вообще считать успехом прогона: сегодня done недостижим в принципе.

Уточнённая приёмка

  • Прогон с 25-46% блоков завершается done, а не banned
  • Прогон 0/5 при 100% блоков по-прежнему banned
  • В counters пишется последовательность/гистограмма исходов, достаточная чтобы измерить длину пачек
  • Правило проверено на исторических прогонах обоих типов (id выше — готовая выборка)
  • Домклик — тот же критерий
**История за 14 дней делает вывод сильнее, а мою оценку — неверной.** Выгрузил все прогоны `avito_detail_backfill` за две недели. **40 из 40 закончились `banned`. Ни один не завершился штатно.** Доля блоков при этом разная — от 25% до 100%: ``` id дата обогащено/попыток блоков доля 4786 24.08 09:16 125/190 47 25% banned 4878 25.08 09:18 61/100 39 39% banned 4910 25.08 21:19 35/71 33 46% banned 5200 28.08 16:47 43/63 20 32% banned 4819 24.08 18:17 8/21 10 48% banned ... 5190 28.08 13:47 0/5 5 100% banned 5140 28.08 01:46 0/5 5 100% banned ``` Прогон, обогативший **125 карточек из 190**, помечен ровно тем же статусом, что и прогон, не обогативший ни одной из пяти. ## Что это значит Правило «N блоков подряд» срабатывает **на каждом прогоне без исключения**. Прогон никогда не заканчивается тем, что очередь разобрана, — он всегда обрывается тripwire'ом, и разница только в том, как далеко успел уйти. **Критерий, который срабатывает всегда, не несёт информации.** Он не отличает выгоревший пул от здорового, потому что говорит «забанен» в обоих случаях. Именно поэтому картина деградации выглядела как обвал: она смешивает удачу отдельного прогона с состоянием источника. ## Поправка к моей предыдущей оценке Я написал «около 18% здоровых прогонов обрываются случайной серией», посчитав вероятность как для независимых событий: `0.32^5 × число позиций`. Эта арифметика верна только при независимости, а данные её опровергают — при 25-32% блоков пятёрки подряд обязаны быть редкими, но они случаются **в каждом прогоне**. Значит **блоки автокоррелированы**: они идут пачками. Получив один блок, следующий запрос получает блок с сильно большей вероятностью — похоже на временный rate-limit, который отпускает. Точную долю ложных срабатываний по имеющимся данным посчитать нельзя: в `counters` лежат только итоги, последовательности попыток нет. Но она заведомо не 18%, а близка к 100% — по факту, а не по модели. ## Следствия для реализации 1. **Порог по доле в скользящем окне** — как и планировалось, но пороги теперь есть на чём калибровать: выгоревшие прогоны дают 100%, здоровые — 25-48%. Граница между ними широкая, где-нибудь около 60-70%. 2. **Пачечность надо учесть явно.** Окно должно быть заметно длиннее типичной пачки, иначе оно повторит дефект серии. Раз пачки длиной ≥5 встречаются в каждом прогоне, окно от 20 попыток. 3. **Логировать последовательность исходов** (хотя бы сжато, в `counters`) — сейчас нечем измерить ни длину пачек, ни эффект любой будущей правки. Без этого следующий разбор снова упрётся в «есть только итоги». 4. Пересмотреть, что вообще считать успехом прогона: сегодня `done` недостижим в принципе. ## Уточнённая приёмка - [ ] Прогон с 25-46% блоков завершается `done`, а не `banned` - [ ] Прогон 0/5 при 100% блоков по-прежнему `banned` - [ ] В `counters` пишется последовательность/гистограмма исходов, достаточная чтобы измерить длину пачек - [ ] Правило проверено на исторических прогонах обоих типов (id выше — готовая выборка) - [ ] Домклик — тот же критерий
bot-backend changed title from Обрыв прогона по серии блоков ложно срабатывает на здоровом пуле — нужен критерий по доле, не по серии to Обрыв по серии блоков срабатывает на КАЖДОМ прогоне (40 из 40 за 14 дней) — критерий не несёт информации 2026-08-28 17:46:23 +00:00
Author
Collaborator

Домклик отделён в #3189 — там нужна своя калибровка, данных по нему нет ни одного прогона. Первый шаг безопасен: собрать гистограмму пачек, не трогая критерий обрыва.

Домклик отделён в #3189 — там нужна своя калибровка, данных по нему нет ни одного прогона. Первый шаг безопасен: собрать гистограмму пачек, не трогая критерий обрыва.
Sign in to join this conversation.
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#3184
No description provided.