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 3m2s
Deploy Trade-In / build-backend (push) Successful in 1m37s
Deploy Trade-In / deploy (push) Successful in 1m54s
66 lines
5.5 KiB
PL/PgSQL
66 lines
5.5 KiB
PL/PgSQL
-- 228_scrape_proxies_browser_health.sql
|
||
-- Здоровье узла ОТДЕЛЬНО для браузерного тракта (#2723).
|
||
--
|
||
-- WHY:
|
||
-- `run_proxy_healthcheck` гоняет через узел обычный httpx-GET к ipify. Боевой сбор
|
||
-- Авито с 02.08 (#2637) ходит через сайдкар браузером: camoufox стартует С ЭТИМ
|
||
-- прокси (geoip-lookup на launch), потом навигация. Это разные свойства узла:
|
||
-- крошечный GET проходит там, где launch/навигация падает (`browser unavailable
|
||
-- (proxy may be down)` — все 90 записанных обрывов сбора именно такие).
|
||
--
|
||
-- Хуже того, оба свойства писались в ОДИН счётчик: боевой /fetch репортит
|
||
-- mark_health(ok=False) → consecutive_fails++, но следующая (≤30 мин) успешная
|
||
-- ipify-проба делает consecutive_fails=0 + enabled=true. Дешёвая проба СТИРАЛА
|
||
-- вердикт дорогого тракта, и узел, мёртвый для браузера, вечно возвращался в
|
||
-- выдачу. Это ровно ошибка #2686 (схлопывание двух диагнозов в один флаг) в
|
||
-- другом месте; разводим её тем же приёмом, что #2711 (`scrape_runs.ban_kind`) —
|
||
-- поле РЯДОМ, а не новое значение существующего флага.
|
||
--
|
||
-- WHAT (три колонки, ни одна не участвует в enabled/consecutive_fails):
|
||
-- browser_fail_streak — подряд-провалы ИМЕННО браузерной пробы, и только те, что
|
||
-- атрибутируются узлу (сайдкар лежит / страница пустая —
|
||
-- не считаются, см. proxy_pool._classify_browser_probe).
|
||
-- Успешная ipify-проба его НЕ обнуляет — в этом весь смысл.
|
||
-- browser_unfit_since — момент, когда streak дошёл до порога. NOT NULL = «жив для
|
||
-- HTTP, непригоден для браузера». acquire() такой узел НЕ
|
||
-- исключает (голодание хуже — #2600/#2638, пул 4 узла), а
|
||
-- отправляет в КОНЕЦ очереди выдачи: его возьмут, только
|
||
-- если свободных пригодных нет.
|
||
-- browser_check_at — когда браузерную пробу гоняли последний раз. Такт у неё
|
||
-- свой, редкий (BROWSER_PROBE_MINUTES): она стоит запуска
|
||
-- camoufox (~8с замерено на проде), ipify — миллисекунды.
|
||
--
|
||
-- IDEMPOTENCY / SAFETY:
|
||
-- ADD COLUMN IF NOT EXISTS × 3, аддитивно, без backfill'а: NULL/0 = «браузерную
|
||
-- пробу ещё не гоняли», ровно то состояние, в котором пул и находится. Ни одна
|
||
-- существующая выборка не меняет результат (все три колонки новые). Повторный
|
||
-- прогон — no-op (auto-apply strict на деплое это требует).
|
||
--
|
||
-- Dependencies: 157_scrape_proxies.sql
|
||
|
||
BEGIN;
|
||
|
||
ALTER TABLE scrape_proxies
|
||
ADD COLUMN IF NOT EXISTS browser_fail_streak integer NOT NULL DEFAULT 0,
|
||
ADD COLUMN IF NOT EXISTS browser_unfit_since timestamptz,
|
||
ADD COLUMN IF NOT EXISTS browser_check_at timestamptz;
|
||
|
||
COMMENT ON COLUMN scrape_proxies.browser_fail_streak IS
|
||
'Подряд-провалы браузерной пробы (сайдкар + camoufox через ЭТОТ узел), '
|
||
'атрибутированные узлу. НЕ обнуляется успешной ipify-пробой — иначе дешёвая '
|
||
'проба стирает вердикт дорогого тракта (#2723). Обнуляется успешной браузерной '
|
||
'пробой. Порог → browser_unfit_since, см. proxy_pool.BROWSER_UNFIT_THRESHOLD.';
|
||
|
||
COMMENT ON COLUMN scrape_proxies.browser_unfit_since IS
|
||
'NOT NULL = узел жив для обычного HTTP, но браузерный тракт через него не '
|
||
'работает (#2723). Это НЕ enabled=false: узел остаётся в пуле и обслуживает '
|
||
'curl-путь, а acquire() лишь отдаёт его последним. Полное выключение по-прежнему '
|
||
'значит «узел мёртв целиком» (серия транспортных сбоев) либо решение оператора.';
|
||
|
||
COMMENT ON COLUMN scrape_proxies.browser_check_at IS
|
||
'Последняя браузерная проба. Такт свой, редкий (proxy_pool.BROWSER_PROBE_MINUTES): '
|
||
'одна такая проба = запуск camoufox (~8с на проде), против миллисекунд у ipify. '
|
||
'На неподтверждённом провале НЕ обновляется — чтобы следующий же цикл '
|
||
'healthcheck подтвердил/опроверг отказ, а не ждал полный такт.';
|
||
|
||
COMMIT;
|