[tradein][scrapers] Browser-sweep'ы зависают ДО первого HTTP (http_requests=0) → zombie/stuck-running на 6ч, источник теряет день #1940

Open
opened 2026-06-27 02:13:53 +00:00 by bot-backend · 1 comment
Collaborator

Симптом (recurring, multi-source)

Несколько browser-based sweep'ов периодически зависают до единого HTTP-запроса и висят в running, пока их не схлопнет zombie-reaper через 6ч. Прод scrape_runs (2026-06-27):

source статус started heartbeat умер http_requests total_seen
avito_city_sweep zombie 06-26 06:49 07:33 (~44мин) 0 0
avito_city_sweep zombie 06-25 06:26 06:44 (~18мин) 0 0
cian_full_load running (4.5ч stale hb) 06-26 20:52 21:37 (~45мин) 0 0
cian_history_backfill zombie 06-26 04:47 0 0

Ключевой признак: http_requests = 0 — воркер виснет на этапе до скрейпа: запуск браузера (AsyncCamoufox в tradein-browser) или connect к мобильному прокси, а не на самих fetch'ах (page.goto имеет BROWSER_NAV_TIMEOUT_MS=60000, значит зависание раньше). Heartbeat умирает через ~18-45 мин после старта, потом тишина.

Это ОТДЕЛЬНО от уже известного

  • НЕ #197068c (avito_full_load UniqueViolation — другой режим, краш на INSERT, уже починен).
  • НЕ #1781 (cian coverage/freshness — про охват якорей/cookies).
  • НЕ #1846 (DomClick QRATOR-бан).
    Это зависание browser-setup до HTTP, общий паттерн для avito/cian browser-sweep'ов.

Текущая митигация (работает как задумано, но мягкая)

reap_zombies() (app/services/scheduler.py:224) помечает run zombie, если heartbeat_at < now() - ZOMBIE_THRESHOLD_HOURS (). Т.е. зависший run занимает слот до 6ч. Снижать порог почти бесполезно: окна расписания дневные (scrape_schedules: avito_city_sweep 6-7h, cian_full_load 20-22h) → освобождённый слот всё равно не переиспользуется в тот же день → источник теряет сутки свежести.

Гипотеза корня (зона scraper-infra / Лёха)

Зависание в tradein-browser sidecar: camoufox launch hang или proxy connect stall (мобильный прокси *.mobileproxy.space иногда висит без ответа). http_requests=0 + heartbeat-смерть до fetch это подтверждают.

Предлагаемые шаги

  1. Диагностика: docker logs tradein-worker + docker logs tradein-browser вокруг времён зависаний (06-26 06:49 / 20:52) — где именно стоп (camoufox launch / proxy connect / WS connect).
  2. Bot-fixable кандидат (нужна проверка на живом браузере): жёсткий timeout на browser-launch / sidecar-call, чтобы зависший setup падал быстро (status=failed, слот свободен, ретраится в окне), а не висел до 6ч-reaper. Сейчас page.goto таймаутится (60с), но фаза launch/connect — похоже без таймаута.
  3. Опц.: health-probe прокси/браузера перед _claim_run (не стартовать sweep если sidecar/прокси не отвечает).
  4. Опц.: снизить ZOMBIE_THRESHOLD_HOURS + добавить in-window retry, чтобы зависание не съедало сутки (только если п.2 не покрывает).

Owner

scraper-infra (Лёха) — нужен доступ к живому browser/proxy для воспроизведения (per .claude/rules/backend.md: web-probing через playwright, не curl).

Найдено в ходе автономного data-health sweep'а 2026-06-27.

## Симптом (recurring, multi-source) Несколько browser-based sweep'ов периодически **зависают до единого HTTP-запроса** и висят в `running`, пока их не схлопнет zombie-reaper через 6ч. Прод `scrape_runs` (2026-06-27): | source | статус | started | heartbeat умер | http_requests | total_seen | |---|---|---|---|---|---| | `avito_city_sweep` | zombie | 06-26 06:49 | 07:33 (~44мин) | **0** | 0 | | `avito_city_sweep` | zombie | 06-25 06:26 | 06:44 (~18мин) | **0** | 0 | | `cian_full_load` | running (4.5ч stale hb) | 06-26 20:52 | 21:37 (~45мин) | **0** | 0 | | `cian_history_backfill` | zombie | 06-26 04:47 | — | **0** | 0 | **Ключевой признак: `http_requests = 0`** — воркер виснет на этапе **до** скрейпа: запуск браузера (`AsyncCamoufox` в `tradein-browser`) или connect к мобильному прокси, а не на самих fetch'ах (`page.goto` имеет `BROWSER_NAV_TIMEOUT_MS=60000`, значит зависание раньше). Heartbeat умирает через ~18-45 мин после старта, потом тишина. ## Это ОТДЕЛЬНО от уже известного - НЕ #197068c (avito_full_load `UniqueViolation` — другой режим, краш на INSERT, уже починен). - НЕ #1781 (cian coverage/freshness — про охват якорей/cookies). - НЕ #1846 (DomClick QRATOR-бан). Это **зависание browser-setup до HTTP**, общий паттерн для avito/cian browser-sweep'ов. ## Текущая митигация (работает как задумано, но мягкая) `reap_zombies()` (`app/services/scheduler.py:224`) помечает run `zombie`, если `heartbeat_at < now() - ZOMBIE_THRESHOLD_HOURS` (**6ч**). Т.е. зависший run занимает слот **до 6ч**. Снижать порог почти бесполезно: окна расписания дневные (`scrape_schedules`: avito_city_sweep 6-7h, cian_full_load 20-22h) → освобождённый слот всё равно не переиспользуется в тот же день → **источник теряет сутки свежести**. ## Гипотеза корня (зона scraper-infra / Лёха) Зависание в `tradein-browser` sidecar: camoufox launch hang или proxy connect stall (мобильный прокси `*.mobileproxy.space` иногда висит без ответа). http_requests=0 + heartbeat-смерть до fetch это подтверждают. ## Предлагаемые шаги 1. **Диагностика:** `docker logs tradein-worker` + `docker logs tradein-browser` вокруг времён зависаний (06-26 06:49 / 20:52) — где именно стоп (camoufox launch / proxy connect / WS connect). 2. **Bot-fixable кандидат (нужна проверка на живом браузере):** жёсткий timeout на browser-launch / sidecar-call, чтобы зависший setup **падал быстро** (status=failed, слот свободен, ретраится в окне), а не висел до 6ч-reaper. Сейчас `page.goto` таймаутится (60с), но фаза launch/connect — похоже без таймаута. 3. **Опц.:** health-probe прокси/браузера перед `_claim_run` (не стартовать sweep если sidecar/прокси не отвечает). 4. **Опц.:** снизить ZOMBIE_THRESHOLD_HOURS + добавить in-window retry, чтобы зависание не съедало сутки (только если п.2 не покрывает). ## Owner scraper-infra (Лёха) — нужен доступ к живому browser/proxy для воспроизведения (per `.claude/rules/backend.md`: web-probing через playwright, не curl). _Найдено в ходе автономного data-health sweep'а 2026-06-27._
bot-backend added the
bug
needs-human
priority/p2
scope/backend
labels 2026-06-27 02:14:42 +00:00
Author
Collaborator

Подтверждение: паттерн повторился, reaper отработал корректно (2026-06-27 03:43 UTC)

cian_full_load (тот самый run, что я отметил как «running 4.5ч stale heartbeat, http_requests=0») → zombie в 03:37reap_zombies (6ч порог) сработал ровно как задумано. Т.е. митигация (reaper) исправна; чинить надо корень — сам hang (browser-launch/proxy-connect зависание до HTTP), а не reaper.

Это укрепляет приоритет п.2 из issue (жёсткий timeout на browser-launch/sidecar-call, чтобы зависший setup падал быстро вместо 6ч-простоя слота). cian_history_backfill при этом восстановился сам (done 03:36) — значит зависания транзиентны (proxy/browser-state), не перманентны → fast-fail + ретрай в окне реально помог бы.

## Подтверждение: паттерн повторился, reaper отработал корректно (2026-06-27 03:43 UTC) `cian_full_load` (тот самый run, что я отметил как «running 4.5ч stale heartbeat, http_requests=0») → **`zombie` в 03:37** — `reap_zombies` (6ч порог) сработал ровно как задумано. Т.е. митигация (reaper) исправна; **чинить надо корень — сам hang** (browser-launch/proxy-connect зависание до HTTP), а не reaper. Это укрепляет приоритет п.2 из issue (жёсткий timeout на browser-launch/sidecar-call, чтобы зависший setup падал быстро вместо 6ч-простоя слота). `cian_history_backfill` при этом восстановился сам (`done` 03:36) — значит зависания транзиентны (proxy/browser-state), не перманентны → fast-fail + ретрай в окне реально помог бы.
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#1940
No description provided.