gendesign/tradein-mvp/backend/data/sql/218_scrape_runs_ban_kind.sql
bot-backend 9e5e9fca08
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
fix(tradein/scraper): статус «забанен» перестаёт выдавать наш сбой за чужой (#2686) (#2711)
2026-08-06 08:18:26 +00:00

72 lines
5.7 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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;