Prod run 423 завис на 7.7ч (healthy ~2.4ч) → reaped как zombie → detail-backlog не уменьшился (21456 листингов ждут detail, 29.3% enriched). Корень: fetch_detail(...) в loop'е без hard-timeout. Один зависший fetch (camoufox/browser hang или curl-stall) блокировал loop навсегда → budget-guard (раз в итерацию) не срабатывал → heartbeat (раз в 25 attempts) не обновлялся → run zombie. Вторичный hang-вектор: _rotate_ip() на блок — тоже без timeout. Fix: - asyncio.wait_for(fetch_detail, timeout=avito_detail_fetch_timeout_s=90s): зависший fetch отменяется → TimeoutError → листинг failed, loop идёт дальше. TimeoutError ловится ДО общего Exception (TimeoutError ⊂ OSError ⊂ Exception), порядок: AvitoBlocked/RateLimited → TimeoutError → Exception. - bound rotate: asyncio.wait_for(_rotate_ip, timeout=settle+30s) + try/except — зависший changeip не роняет run. - config: avito_detail_fetch_timeout_s (ENV AVITO_DETAIL_FETCH_TIMEOUT_S). - admin: POST /scrape/avito-detail-backfill (batch_size, budget_sec) — on-demand прогон/верификация (основной schedule window-gated 09-12 UTC). Восстанавливает throughput detail-очереди (точные coords #1967 + house_type/kitchen). |
||
|---|---|---|
| .. | ||
| api | ||
| core | ||
| observability | ||
| schemas | ||
| services | ||
| tasks | ||
| __init__.py | ||
| main.py | ||
| scheduler_main.py | ||