All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 2m58s
Deploy Trade-In / build-backend (push) Successful in 1m37s
Deploy Trade-In / deploy (push) Successful in 1m44s
72 lines
5.7 KiB
SQL
72 lines
5.7 KiB
SQL
-- 218_scrape_runs_ban_kind.sql
|
||
-- scrape_runs.ban_kind — статус 'banned' перестаёт смешивать наш сбой с чужим (#2686).
|
||
--
|
||
-- Dependencies: 015_scrape_runs.sql (создала таблицу и CHECK по status).
|
||
-- Apply after: 217_position_in_serp_unexpressible.sql
|
||
-- Идемпотентно: ADD COLUMN IF NOT EXISTS + DROP/ADD CONSTRAINT + UPDATE только там,
|
||
-- где ban_kind ещё NULL.
|
||
--
|
||
-- ── ЧТО НАЙДЕНО ──────────────────────────────────────────────────────────────
|
||
-- Из 115 avito-прогонов со статусом 'banned' (замер на проде 2026-08-06):
|
||
-- 90 — «browser unavailable (proxy may be down)» — 503 НАШЕГО браузерного
|
||
-- сайдкара (05.07-03.08), площадка ни при чём;
|
||
-- 2 — прочие ошибки того же сайдкара (04.07, 15.07);
|
||
-- 10 — «Avito SERP firewall (browser-mode) … IP banned» — реальная блокировка
|
||
-- площадкой (16.06-06.08);
|
||
-- 11 — HTTP 429/403 (30.05-19.06);
|
||
-- 2 — прочее (21.06, 23.06).
|
||
-- То есть 92 из 115 (80%) прогонов, помеченных «нас забанили», — отказ нашей
|
||
-- собственной инфраструктуры. Оба исхода писали РАЗНЫЙ текст ошибки и получали
|
||
-- ОДИН статус: различитель лежал в данных и терялся ровно в момент присвоения.
|
||
--
|
||
-- ── ЦЕНА, КОТОРАЯ УЖЕ УПЛАЧЕНА ───────────────────────────────────────────────
|
||
-- Миграция 206 прочитала статус буквально — как «площадка распознаёт наш паттерн» —
|
||
-- и на этом основании замедлила avito_full_load_exhaustive более чем вдвое, переведя
|
||
-- на недельный такт. Основание было ложным. Возврат такта сюда НЕ входит: он вынесен
|
||
-- в #2687 на данные 9-10.08.
|
||
--
|
||
-- ── ПОЧЕМУ КОЛОНКА, А НЕ НОВЫЙ СТАТУС ────────────────────────────────────────
|
||
-- 1. У 'banned' есть побочная функция: в отличие от 'failed' он СОХРАНЯЕТ
|
||
-- done_buckets-чекпоинт пройденных бакетов. Она нужна обоим исходам — следующий
|
||
-- прогон не должен начинать с нуля ни при нашем отказе, ни при блокировке.
|
||
-- Оставив статус, получаем её даром.
|
||
-- 2. Новое значение статуса пришлось бы доучить пяти местам, каждое из которых
|
||
-- молча даёт неверный ответ, если про него забыть: этот CHECK, IN-списки обоих
|
||
-- сторожей в orchestration/runs.py, Literal-фильтр admin API и хардкод-список
|
||
-- статусов во фронте (RunsTable.tsx). Это ровно тот класс оборванной проводки,
|
||
-- из-за которого задача и появилась.
|
||
-- 3. Прогон в обоих случаях требует одного обращения (оборвать, сохранить частичное);
|
||
-- различается только ДИАГНОЗ — метаданное, не состояние.
|
||
--
|
||
-- В рантайме значение несётся от МЕСТА ПОРОЖДЕНИЯ отказа (тип исключения
|
||
-- AvitoSidecarUnavailableError), а не разбирается из текста ошибки постфактум.
|
||
-- Разбор текста ниже — РАЗОВАЯ ретро-классификация уже накопленной истории; для
|
||
-- новых строк этот путь не используется.
|
||
|
||
ALTER TABLE scrape_runs
|
||
ADD COLUMN IF NOT EXISTS ban_kind text;
|
||
|
||
COMMENT ON COLUMN scrape_runs.ban_kind IS
|
||
'Диагноз status=''banned'' (#2686): platform — площадка заблокировала '
|
||
'(firewall/403/captcha); infra — не отдала НАША инфраструктура (браузерный '
|
||
'сайдкар/прокси). NULL для прогонов с другим статусом. Пишется из типа '
|
||
'исключения в момент отказа, не из текста ошибки.';
|
||
|
||
ALTER TABLE scrape_runs DROP CONSTRAINT IF EXISTS scrape_runs_ban_kind_check;
|
||
ALTER TABLE scrape_runs
|
||
ADD CONSTRAINT scrape_runs_ban_kind_check
|
||
CHECK (ban_kind IS NULL OR ban_kind IN ('platform', 'infra'));
|
||
|
||
-- Ретро-классификация истории (разово, только там, где ещё NULL). Порядок веток
|
||
-- важен: маркер сайдкара проверяется первым, потому что текст полного обхода
|
||
-- оборачивает его в свой префикс («avito full load aborted: avito SERP
|
||
-- browser-sidecar error (page=1): browser unavailable (proxy may be down)»).
|
||
UPDATE scrape_runs
|
||
SET ban_kind = CASE
|
||
WHEN error ILIKE '%browser-sidecar error%'
|
||
OR error ILIKE '%browser unavailable%'
|
||
OR error ILIKE '%proxy may be down%' THEN 'infra'
|
||
ELSE 'platform'
|
||
END
|
||
WHERE status = 'banned'
|
||
AND ban_kind IS NULL;
|