tradein/domclick: после #3237 настоящий отказ площадки перестал банить узел — уехал в ветку «сбой транспорта» #3239

Closed
opened 2026-08-29 16:02:29 +00:00 by lekss361 · 0 comments
Owner

Что случилось

PR #3237 научил сайдкар опознавать статический отказ Домклика самостоятельно
(_is_domclick_refusalBanPageDetectedError). Это правильно и работает. Но
вместе с этим настоящий ban-сигнал переехал из ветки «подтверждённый маркер» в
ветку «сетевой сбой», где report_ban намеренно НЕ зовётся.

Механизм (прослежен построчно)

Было: отказ приезжал наверх как HTML + HTTP 401 → parse_detail_html ловил
маркеры → DomClickBlockedError, blocked.status = 401report_ban()
(detail.py:565) → узел забанен, пул ротируется. ban_kind = platform.

Стало: отказ ловит сайдкар → BanPageDetectedErrorfetch_handler
отвечает HTTP 500 (browser/server.py:964) → _raise_for_sidecar_status
поднимает HTTPStatusErrorbrowser_fetcher.py:781-783 явно ставит
last_response_status = None и пробрасывает → в detail.py срабатывает
except Exception (строки 546-555), а она по построению не зовёт
report_ban («не подтверждённый маркер-бан, а сбой транспорта», #2600 п.4) →
DomClickBlockedError(status=None)_ban_kind_of_blockunknown.

Замер на проде

Прогон 5287 (29.08, 15:56 UTC, уже на образе с фиксом):

{"failed": 0, "blocked": 3, "enriched": 0, "attempted": 3,
 "ban_kinds": {"unknown": 3}, "duration_sec": 97}

Раньше на том же месте было {"platform": 3}. В scrape_proxy_source_bans
после прогона ни одной новой записи — при том, что в логах сайдкара шесть
статический отказ площадки подряд по трём карточкам. Пул считает отказавшие
узлы здоровыми и выдаст их следующему прогону.

Почему это важнее, чем кажется

Это не косметика счётчиков: platform — единственный диагноз, который запускает
ротацию IP. Сейчас реальный отказ площадки её не запускает, то есть мы будем
долбиться в один и тот же отказывающий узел вместо перехода на свободный.

Что нужно

BanPageDetectedError от сайдкара семантически — тот же подтверждённый
маркер-детект, что и раньше ловил parse_detail_html. Он должен попадать на
ban-путь, а не на транспортный. Ориентир правки:

  1. Сайдкар: в теле ошибки отдавать структурный признак ("ban_page": true) и
    апстрим-статус, а не только строку в "error".
  2. BrowserFetcher: поднять признак наверх типизированно (не матчить текст).
  3. providers/domclick/detail.py: в except Exception различить эти два случая —
    подтверждённый отказ уводить в report_ban, транспортный сбой оставить как есть.

Матчинг по подстроке в тексте исключения — не решение: _raise_for_sidecar_status
обрезает тело до 300 символов, и формулировка отказа менялась дважды за месяц.

Приёмка

Прогон domclick_detail_backfill на отказывающем узле: ban_kinds = platform,
в scrape_proxy_source_bans появляется запись по этому узлу, следующий прогон
берёт ДРУГОЙ узел. При этом незавершённое рукопожатие (#3237) по-прежнему НЕ
банит — обе ветки должны быть покрыты тестами раздельно.

Контекст

  • #3237 (источник регрессии), #3222, #3196, #2600 п.4 (почему транспортная ветка
    сознательно не репортит), #2764 (почему не назначаем причину, которую не установили)
  • Разбор причины исходной поломки: vault fixes/Fix_Domclick_Handshake_Miscalled_Block_Aug29.md
## Что случилось PR #3237 научил сайдкар опознавать статический отказ Домклика самостоятельно (`_is_domclick_refusal` → `BanPageDetectedError`). Это правильно и работает. Но вместе с этим настоящий ban-сигнал переехал из ветки «подтверждённый маркер» в ветку «сетевой сбой», где `report_ban` намеренно НЕ зовётся. ## Механизм (прослежен построчно) **Было:** отказ приезжал наверх как HTML + HTTP 401 → `parse_detail_html` ловил маркеры → `DomClickBlockedError`, `blocked.status = 401` → `report_ban()` (`detail.py:565`) → узел забанен, пул ротируется. `ban_kind` = `platform`. **Стало:** отказ ловит сайдкар → `BanPageDetectedError` → `fetch_handler` отвечает **HTTP 500** (`browser/server.py:964`) → `_raise_for_sidecar_status` поднимает `HTTPStatusError` → `browser_fetcher.py:781-783` явно ставит `last_response_status = None` и пробрасывает → в `detail.py` срабатывает `except Exception` (строки 546-555), а она по построению **не зовёт** `report_ban` («не подтверждённый маркер-бан, а сбой транспорта», #2600 п.4) → `DomClickBlockedError(status=None)` → `_ban_kind_of_block` → `unknown`. ## Замер на проде Прогон 5287 (29.08, 15:56 UTC, уже на образе с фиксом): ``` {"failed": 0, "blocked": 3, "enriched": 0, "attempted": 3, "ban_kinds": {"unknown": 3}, "duration_sec": 97} ``` Раньше на том же месте было `{"platform": 3}`. В `scrape_proxy_source_bans` после прогона **ни одной новой записи** — при том, что в логах сайдкара шесть `статический отказ площадки` подряд по трём карточкам. Пул считает отказавшие узлы здоровыми и выдаст их следующему прогону. ## Почему это важнее, чем кажется Это не косметика счётчиков: `platform` — единственный диагноз, который запускает ротацию IP. Сейчас реальный отказ площадки её не запускает, то есть мы будем долбиться в один и тот же отказывающий узел вместо перехода на свободный. ## Что нужно `BanPageDetectedError` от сайдкара семантически — тот же подтверждённый маркер-детект, что и раньше ловил `parse_detail_html`. Он должен попадать на ban-путь, а не на транспортный. Ориентир правки: 1. Сайдкар: в теле ошибки отдавать структурный признак (`"ban_page": true`) и апстрим-статус, а не только строку в `"error"`. 2. `BrowserFetcher`: поднять признак наверх типизированно (не матчить текст). 3. `providers/domclick/detail.py`: в `except Exception` различить эти два случая — подтверждённый отказ уводить в `report_ban`, транспортный сбой оставить как есть. Матчинг по подстроке в тексте исключения — не решение: `_raise_for_sidecar_status` обрезает тело до 300 символов, и формулировка отказа менялась дважды за месяц. ## Приёмка Прогон `domclick_detail_backfill` на отказывающем узле: `ban_kinds` = `platform`, в `scrape_proxy_source_bans` появляется запись по этому узлу, следующий прогон берёт ДРУГОЙ узел. При этом незавершённое рукопожатие (#3237) по-прежнему НЕ банит — обе ветки должны быть покрыты тестами раздельно. ## Контекст - #3237 (источник регрессии), #3222, #3196, #2600 п.4 (почему транспортная ветка сознательно не репортит), #2764 (почему не назначаем причину, которую не установили) - Разбор причины исходной поломки: vault `fixes/Fix_Domclick_Handshake_Miscalled_Block_Aug29.md`
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#3239
No description provided.