[HIGH] tradein/imv: домовая оценка Авито мертва 34 дня — 0 сохранённых из 35 попыток в каждом прогоне, все прогоны done #2698

Closed
opened 2026-08-06 05:50:47 +00:00 by bot-backend · 4 comments
Collaborator

Найдено при разборе фотографий подсказок IMV (эпик #2674, PR #2693). Само поле фото починено; продюсер, который его наполняет, не работает 34 дня, и это не видно ни по одному статусу.

Что показывает прод

Последняя удачная домовая оценка Авито — 2026-07-03 17:21. С тех пор ни одной.

Четыре последних прогона house_imv_backfill, счётчики дословно:

3231 | 2026-08-05 16:45 | done | {"saved": 0, "errors": 35, "checked": 50, "skipped": 15}
2996 | 2026-08-02 16:41 | done | {"saved": 0, "errors": 35, "checked": 50, "skipped": 15}
2900 | 2026-08-01 16:54 | done | {"saved": 0, "errors": 35, "checked": 50, "skipped": 15}
2817 | 2026-07-31 16:53 | done | {"saved": 0, "errors": 34, "checked": 50, "skipped": 16}

Тридцать пять ошибок из тридцати пяти попыток — и статус done. Прогон, у которого ноль успехов при стопроцентном отказе, отчитывается так же, как полностью успешный. Это ровно тот класс, который уже чинили для Домклика (#2657) и Циана (#2625/#2658): здесь он не закрыт.

Состояние домов:

imv_status Домов
pending 5 768
ok 1 668 (последний 03.07)
transient_error 1 414
no_params 344
no_address 217
error 46

Причины отказов

Причина Домов Последний раз
503 Service Unavailable от tradein-browser:3000/fetch-json 1 240 02.08
500 Internal Server Error оттуда же 83 05.08
403 — auth rejected / quota exceeded 31 05.08
All connection attempts failed 28 15.07

Отказ приходит с нашего собственного браузерного сайдкара, а не от площадки. При этом сайдкар сейчас жив: docker exec tradein-scraper curl -X POST http://tradein-browser:3000/fetch-json -d '{"url":"https://www.avito.ru/robots.txt"}'200. Значит валится не сервис целиком, а конкретный путь — геокодер А. Свежайшая ошибка уже не 503, а 500 плюс 403 по авторизации, то есть режим отказа за месяц менялся и никто этого не заметил.

Почему это стоит денег

Домовая оценка Авито — один из входов эстиматора. Он молча отсутствует с 3 июля: 5 768 домов в pending никогда не будут оценены при текущем темпе, а 1 414 висят в transient_error, который по имени обещает, что попытка повторится.

Что нужно сделать

  1. Честность прогона. saved == 0 при errors > 0 — не done. Паттерн уже реализован для других источников, взять его.
  2. Разобрать 500/403 на пути геокодера А — это отдельная работа: /fetch-json в целом отвечает, значит дело в самом запросе или в его прокси/авторизации.
  3. Оповещение — этот случай неотличим от здорового ровно потому, что наружу не уходит ничего (#2673).

Связано: #2674, #2673, #2657, #2625, #2686 (там же — наш собственный сайдкар, записанный как бан площадки), #2693.

Найдено при разборе фотографий подсказок IMV (эпик #2674, PR #2693). Само поле фото починено; продюсер, который его наполняет, **не работает 34 дня**, и это не видно ни по одному статусу. ## Что показывает прод Последняя удачная домовая оценка Авито — **2026-07-03 17:21**. С тех пор ни одной. Четыре последних прогона `house_imv_backfill`, счётчики дословно: ``` 3231 | 2026-08-05 16:45 | done | {"saved": 0, "errors": 35, "checked": 50, "skipped": 15} 2996 | 2026-08-02 16:41 | done | {"saved": 0, "errors": 35, "checked": 50, "skipped": 15} 2900 | 2026-08-01 16:54 | done | {"saved": 0, "errors": 35, "checked": 50, "skipped": 15} 2817 | 2026-07-31 16:53 | done | {"saved": 0, "errors": 34, "checked": 50, "skipped": 16} ``` Тридцать пять ошибок из тридцати пяти попыток — и статус `done`. Прогон, у которого **ноль успехов при стопроцентном отказе**, отчитывается так же, как полностью успешный. Это ровно тот класс, который уже чинили для Домклика (#2657) и Циана (#2625/#2658): здесь он не закрыт. Состояние домов: | `imv_status` | Домов | |---|---:| | pending | 5 768 | | ok | 1 668 *(последний 03.07)* | | transient_error | 1 414 | | no_params | 344 | | no_address | 217 | | error | 46 | ## Причины отказов | Причина | Домов | Последний раз | |---|---:|---| | `503 Service Unavailable` от `tradein-browser:3000/fetch-json` | 1 240 | 02.08 | | `500 Internal Server Error` оттуда же | 83 | 05.08 | | `403 — auth rejected / quota exceeded` | 31 | 05.08 | | `All connection attempts failed` | 28 | 15.07 | Отказ приходит с **нашего собственного** браузерного сайдкара, а не от площадки. При этом сайдкар сейчас жив: `docker exec tradein-scraper curl -X POST http://tradein-browser:3000/fetch-json -d '{"url":"https://www.avito.ru/robots.txt"}'` → **200**. Значит валится не сервис целиком, а конкретный путь — геокодер А. Свежайшая ошибка уже не 503, а 500 плюс 403 по авторизации, то есть режим отказа за месяц менялся и никто этого не заметил. ## Почему это стоит денег Домовая оценка Авито — один из входов эстиматора. Он молча отсутствует с 3 июля: 5 768 домов в `pending` никогда не будут оценены при текущем темпе, а 1 414 висят в `transient_error`, который по имени обещает, что попытка повторится. ## Что нужно сделать 1. **Честность прогона.** `saved == 0` при `errors > 0` — не `done`. Паттерн уже реализован для других источников, взять его. 2. **Разобрать 500/403 на пути геокодера А** — это отдельная работа: `/fetch-json` в целом отвечает, значит дело в самом запросе или в его прокси/авторизации. 3. **Оповещение** — этот случай неотличим от здорового ровно потому, что наружу не уходит ничего (#2673). Связано: #2674, #2673, #2657, #2625, #2686 (там же — наш собственный сайдкар, записанный как бан площадки), #2693.
Author
Collaborator

Разбор: два дефекта, и один из них уже закрыт до начала работы

Часть B («честность прогона») — уже на проде, ничего делать не нужно

Правило saved == 0 при errors > 0 → не 'done' смержено 06.08 в 00:29 коммитом 0815319e (product_handlers.py:427), счётчики в выделенные колонки — 4b4ab8b3 (total_seen = checked, new_count = saved). Обязательный тест тоже есть: tests/test_house_imv_params_honesty.py::test_zero_saved_with_errors_is_not_done (saved=0 / errors=35 / skipped=15 → mark_failed) плюс анти-оверрич test_honest_empty_stays_done.

Проверено в живом контейнере, а не по релизу:

$ docker exec tradein-scraper grep -c "saved=0 при errors" /app/app/services/product_handlers.py
2
$ docker exec tradein-scraper grep -n "total_seen.*result.checked" /app/app/services/product_handlers.py
419:            "total_seen": result.checked,

Следующий прогон — 08.08 16:13 UTC (scrape_schedules.next_run_at, interval_days: 3, а не «раз в сутки»). Он будет первым с честным статусом.

Замечание про #2703: у этой задачи ямы «сторож читает total_seen, которого нет» уже нет — 4b4ab8b3 её заполняет. Но здоровый прогон теперь даёт total_seen = checked = 50 и при 100% отказов тоже (checked считает все дома, включая упавшие), так что «нулевой» сторож этот класс не поймает в принципе — ловит его сторож подряд-идущих failed. Для house_imv это работает; общая слепота backfill-словаря остаётся за #2703.

Часть A — почему ноль. Корневая причина найдена, PR #2708

Не «геокодер A» как таковой и не протухшая учётка Авито. В IMV-флоу авторизации нет вообще: providers/avito/imv.py шлёт анонимные XHR (_COMMON_HEADERS — Accept/Referer/Sec-Fetch, ни куки, ни токена). Формулировка «403 — auth rejected / quota exceeded» — это наш собственный текст в _raise_for_status_categorized для любого 401/403, а не сообщение площадки. Обновлять по Авито нечего.

Настоящая разница между путём, который отвечает 200, и путём, который лежал 34 дня, — одно поле в теле запроса к сайдкару:

house_imv_backfill.py:581 конструировал BrowserFetcher(source="avito", endpoint=...) без proxy_provider / use_pool / environment — единственный avito-путь без проводки пула (сравнить: orchestration/pipeline.py:519). Без них BrowserFetcher._current_proxy() возвращает (None, None), поле proxy в тело POST /fetch-json не кладётся, и сайдкар берёт свой env-прокси SCRAPER_PROXY_URL. На проде это узел пула id=1asocks-residential-1, provider_affinity='domclick', тот самый «один чистый residential-адрес», который proxy_pool.acquire('avito') не выдал бы никогда (фильтр affinity IN (provider,'any') + защита последнего узла выделенной affinity от fallback, 173_scrape_proxies_add_domclick_affinity.sql).

Контрольная группа — те же сутки, тот же сайдкар, тот же инстанс камуфокса:

дата avito_city_sweep avito_newbuilding_sweep house_imv_backfill
01.08 78 seen / 69 new 484 / 447 0 saved / 35 errors
02.08 269 / 132 397 / 191 0 / 35
05.08 300 / 122 508 / 255 0 / 35

Sweep'ы пул подключают — и работают. IMV не подключает — и не работает. Больше между ними отличий нет.

Смена режима отказа 503 → 500+403 объясняется тем же: 503 отдаёт сам сайдкар, когда камуфокс не поднялся на env-прокси (server.py::_ensure_browserbrowser unavailable (proxy may be down)); после прокси-волны 04-05.08 (#2634 / #2640 / #2600) env-узел стал подниматься — и запросы через него доехали до площадки, где получили либо Page.goto: NS_ERROR_PROXY_BAD_GATEWAY (сайдкар → 500), либо 403 от Авито. Механизм 500 подтверждён живым логом сайдкара 06.08 04:12 на том же env-прокси:

ERROR tradein-browser[generic]: fetch error url='https://bff-search-web.domclick.ru/...':
  Error: Page.goto: NS_ERROR_PROXY_BAD_GATEWAY

Побочный эффект той же дыры: запрос без proxy роняет сайдкару желаемый прокси на env → _ensure_browser релончит камуфокс на каждый дом (в логе видно прокси изменился (override=False) — relaunch), то есть путь IMV ещё и сбивал тёплый браузер sweep'ам.

Почему это не заметили 34 дня — второй дефект, тоже в PR

Сайдкар кладёт причину отказа в тело ({"error": "browser unavailable (proxy may be down)"}, {"error": "Error: Page.goto: NS_ERROR_PROXY_BAD_GATEWAY"}), а resp.raise_for_status() печатает только код статуса. Ровно эта строка и лежала в houses.imv_error_reason у 1240 домов:

Avito geocode A network error: Server error '503 Service Unavailable' for url 'http://tradein-browser:3000/fetch-json'

Отказ был виден, причина — нет. Общий _raise_for_sidecar_status в browser_fetcher (оба эндпоинта, все вызывающие) добавляет тело в текст ошибки; тип исключения прежний, retry-политика не меняется.

Уточнение к таблице из шапки

no listings with rooms+area — не отказ, а пропуск (skipped, 15-16 домов на прогон): у дома нет ни одного объявления с комнатностью и площадью. В счётчиках он и так отдельно, но в списке причин отказа его лучше не держать.

Живых запросов к Авито не делалось

Всё выше — из прод-БД, docker logs tradein-browser и кода. Сайдкар отдельно не дёргался.

## Разбор: два дефекта, и один из них уже закрыт до начала работы ### Часть B («честность прогона») — уже на проде, ничего делать не нужно Правило `saved == 0 при errors > 0 → не 'done'` смержено **06.08 в 00:29** коммитом 0815319e (`product_handlers.py:427`), счётчики в выделенные колонки — 4b4ab8b3 (`total_seen = checked`, `new_count = saved`). Обязательный тест тоже есть: `tests/test_house_imv_params_honesty.py::test_zero_saved_with_errors_is_not_done` (saved=0 / errors=35 / skipped=15 → `mark_failed`) плюс анти-оверрич `test_honest_empty_stays_done`. Проверено в живом контейнере, а не по релизу: ``` $ docker exec tradein-scraper grep -c "saved=0 при errors" /app/app/services/product_handlers.py 2 $ docker exec tradein-scraper grep -n "total_seen.*result.checked" /app/app/services/product_handlers.py 419: "total_seen": result.checked, ``` Следующий прогон — **08.08 16:13 UTC** (`scrape_schedules.next_run_at`, `interval_days: 3`, а не «раз в сутки»). Он будет первым с честным статусом. Замечание про #2703: у этой задачи ямы «сторож читает `total_seen`, которого нет» уже нет — 4b4ab8b3 её заполняет. Но здоровый прогон теперь даёт `total_seen = checked = 50` **и при 100% отказов тоже** (checked считает все дома, включая упавшие), так что «нулевой» сторож этот класс не поймает в принципе — ловит его сторож подряд-идущих `failed`. Для house_imv это работает; общая слепота backfill-словаря остаётся за #2703. ### Часть A — почему ноль. Корневая причина найдена, PR #2708 **Не «геокодер A» как таковой и не протухшая учётка Авито.** В IMV-флоу авторизации нет вообще: `providers/avito/imv.py` шлёт анонимные XHR (`_COMMON_HEADERS` — Accept/Referer/Sec-Fetch, ни куки, ни токена). Формулировка «403 — auth rejected / quota exceeded» — это **наш собственный текст** в `_raise_for_status_categorized` для любого 401/403, а не сообщение площадки. Обновлять по Авито нечего. Настоящая разница между путём, который отвечает 200, и путём, который лежал 34 дня, — **одно поле в теле запроса к сайдкару**: `house_imv_backfill.py:581` конструировал `BrowserFetcher(source="avito", endpoint=...)` без `proxy_provider` / `use_pool` / `environment` — единственный avito-путь без проводки пула (сравнить: `orchestration/pipeline.py:519`). Без них `BrowserFetcher._current_proxy()` возвращает `(None, None)`, поле `proxy` в тело `POST /fetch-json` не кладётся, и сайдкар берёт свой env-прокси `SCRAPER_PROXY_URL`. На проде это узел пула `id=1` — `asocks-residential-1`, `provider_affinity='domclick'`, тот самый «один чистый residential-адрес», который `proxy_pool.acquire('avito')` не выдал бы **никогда** (фильтр `affinity IN (provider,'any')` + защита последнего узла выделенной affinity от fallback, `173_scrape_proxies_add_domclick_affinity.sql`). **Контрольная группа** — те же сутки, тот же сайдкар, тот же инстанс камуфокса: | дата | avito_city_sweep | avito_newbuilding_sweep | house_imv_backfill | |---|---|---|---| | 01.08 | 78 seen / 69 new | 484 / 447 | 0 saved / 35 errors | | 02.08 | 269 / 132 | 397 / 191 | 0 / 35 | | 05.08 | 300 / 122 | 508 / 255 | 0 / 35 | Sweep'ы пул подключают — и работают. IMV не подключает — и не работает. Больше между ними отличий нет. Смена режима отказа 503 → 500+403 объясняется тем же: 503 отдаёт сам сайдкар, когда камуфокс не поднялся на env-прокси (`server.py::_ensure_browser` → `browser unavailable (proxy may be down)`); после прокси-волны 04-05.08 (#2634 / #2640 / #2600) env-узел стал подниматься — и запросы через него доехали до площадки, где получили либо `Page.goto: NS_ERROR_PROXY_BAD_GATEWAY` (сайдкар → 500), либо 403 от Авито. Механизм 500 подтверждён живым логом сайдкара 06.08 04:12 на том же env-прокси: ``` ERROR tradein-browser[generic]: fetch error url='https://bff-search-web.domclick.ru/...': Error: Page.goto: NS_ERROR_PROXY_BAD_GATEWAY ``` Побочный эффект той же дыры: запрос без `proxy` роняет сайдкару *желаемый* прокси на env → `_ensure_browser` релончит камуфокс на каждый дом (в логе видно `прокси изменился (override=False) — relaunch`), то есть путь IMV ещё и сбивал тёплый браузер sweep'ам. ### Почему это не заметили 34 дня — второй дефект, тоже в PR Сайдкар кладёт причину отказа в тело (`{"error": "browser unavailable (proxy may be down)"}`, `{"error": "Error: Page.goto: NS_ERROR_PROXY_BAD_GATEWAY"}`), а `resp.raise_for_status()` печатает только код статуса. Ровно эта строка и лежала в `houses.imv_error_reason` у 1240 домов: ``` Avito geocode A network error: Server error '503 Service Unavailable' for url 'http://tradein-browser:3000/fetch-json' ``` Отказ был виден, причина — нет. Общий `_raise_for_sidecar_status` в `browser_fetcher` (оба эндпоинта, все вызывающие) добавляет тело в текст ошибки; тип исключения прежний, retry-политика не меняется. ### Уточнение к таблице из шапки `no listings with rooms+area` — не отказ, а пропуск (`skipped`, 15-16 домов на прогон): у дома нет ни одного объявления с комнатностью и площадью. В счётчиках он и так отдельно, но в списке причин отказа его лучше не держать. ### Живых запросов к Авито не делалось Всё выше — из прод-БД, `docker logs tradein-browser` и кода. Сайдкар отдельно не дёргался.
Author
Collaborator

Корень найден — и это не то, что предполагалось в теле задачи

Смержено в PR #2708 (c66e18cd).

Домовая оценка была единственным avito-путём, который строил браузерный клиент БЕЗ подключения к пулу прокси. Все остальные пути передают proxy_provider/use_pool/environment; этот — нет. Из-за этого поле proxy не попадало в тело запроса к сайдкару, и сайдкар брал свой собственный SCRAPER_PROXY_URL из окружения.

На проде это узел пула id=1 asocks-residential-1 с provider_affinity = 'domclick' — то есть узел, который proxy_pool.acquire('avito') не выдал бы никогда: его защищает и фильтр affinity, и правило, запрещающее забирать последний узел выделенной affinity в fallback. Домовая оценка ходила через прокси, предназначенный другому источнику, в обход собственного пула.

Доказательство — контрольная группа в тех же сутках

Тот же сайдкар, тот же инстанс браузера, те же сутки:

01.08   avito_city_sweep 78 seen / 69 new   ·  avito_newbuilding_sweep 484/447  ·  house_imv 0 saved / 35 errors
02.08   269/132                             ·  397/191                          ·  0/35
05.08   300/122                             ·  508/255                          ·  0/35

Соседние задачи по тому же источнику работают. Отличие ровно одно — поле proxy в запросе.

Механизм 500 подтверждён живым логом сайдкара 06.08 04:12 на том же env-прокси: Page.goto: NS_ERROR_PROXY_BAD_GATEWAY → перехват → HTTP 500. Смена режима отказа 503 → 500 в начале августа объясняется прокси-волной #2634/#2640/#2600: узел стал подниматься, и отказ переехал с «браузер не стартовал» на «навигация через него не проходит». То есть смена формулировки была следствием чужой починки, а не новой поломки.

Почему это не видели 34 дня

Сайдкар кладёт причину отказа в тело ответа, а raise_for_status() печатает только код. Ровно эта обрезанная строка и лежала у 1240 домов в imv_error_reason — код без причины. Добавлен общий разбор тела на обоих эндпоинтах сайдкара; тип исключения прежний, значит политика повторов не меняется.

Три предпосылки этой задачи оказались неверны — поправка к тексту выше

1. «403 — auth rejected / quota exceeded» НЕ означает протухшую учётную запись Авито. В IMV-флоу авторизации нет вообще: это анонимные XHR, без куки и токена. Строка «auth rejected / quota exceeded» — наш собственный текст, которым код подписывает любой 401/403. Владельцу по Авито обновлять нечего, и я снимаю это как ложный след (в сводке #2704 соответствующее уточнение внесено).

2. «Валится конкретный путь геокодера A» — неверно. Геокодер A просто первый из трёх запросов флоу, поэтому падал всегда он. Сломан был транспорт всего флоу.

3. Честность статуса уже была починена — коммитом 0815319e 06.08 в 00:29, то есть до начала работы над этой задачей, вместе с тестом test_zero_saved_with_errors_is_not_done. Поэтому PR один, а не два.

Заодно: задача бежит раз в 3 дня, а не раз в сутки (interval_days: 3, наследие миграции 206).

Статус проверки

Правка на проде: маркер _raise_for_sidecar_status (функции не существовало до диффа) присутствует в живом контейнере tradein-scraper, проводка пула — на месте. Контейнер пересоздан, потому что дифф задел packages/scraper-kit/**, а этот путь в allowlist есть.

Функционально не проверено: следующий прогон — 2026-08-08 16:13 UTC. Прогона после деплоя не было. Это «не проверено», а не «работает» и не «не работает». Задачу оставляю открытой до первого прогона; критерий приёмки — saved > 0 и исчезновение NS_ERROR_PROXY_BAD_GATEWAY из причин.

Осталось за рамками

  • report_ban на IMV-пути не подключён: 403 от Авито в пул не доезжает. Нужен критерий «бан», а не «любой 403» — отдельная работа.
  • app/services/house_imv_backfill.py и product_handlers.py НЕ входят в scraper-allowlist деплоя. Правка только в них доехала бы до бэкенда и не доехала до скрапера, который их исполняет. Ещё один довод за #2680.
## Корень найден — и это не то, что предполагалось в теле задачи Смержено в PR #2708 (`c66e18cd`). **Домовая оценка была единственным avito-путём, который строил браузерный клиент БЕЗ подключения к пулу прокси.** Все остальные пути передают `proxy_provider`/`use_pool`/`environment`; этот — нет. Из-за этого поле `proxy` не попадало в тело запроса к сайдкару, и сайдкар брал свой собственный `SCRAPER_PROXY_URL` из окружения. На проде это узел пула `id=1 asocks-residential-1` с `provider_affinity = 'domclick'` — то есть узел, который `proxy_pool.acquire('avito')` **не выдал бы никогда**: его защищает и фильтр affinity, и правило, запрещающее забирать последний узел выделенной affinity в fallback. Домовая оценка ходила через прокси, предназначенный другому источнику, в обход собственного пула. ## Доказательство — контрольная группа в тех же сутках Тот же сайдкар, тот же инстанс браузера, те же сутки: ``` 01.08 avito_city_sweep 78 seen / 69 new · avito_newbuilding_sweep 484/447 · house_imv 0 saved / 35 errors 02.08 269/132 · 397/191 · 0/35 05.08 300/122 · 508/255 · 0/35 ``` Соседние задачи по тому же источнику работают. Отличие ровно одно — поле `proxy` в запросе. Механизм 500 подтверждён живым логом сайдкара 06.08 04:12 на том же env-прокси: `Page.goto: NS_ERROR_PROXY_BAD_GATEWAY` → перехват → HTTP 500. Смена режима отказа 503 → 500 в начале августа объясняется прокси-волной #2634/#2640/#2600: узел стал подниматься, и отказ переехал с «браузер не стартовал» на «навигация через него не проходит». То есть смена формулировки была следствием чужой починки, а не новой поломки. ## Почему это не видели 34 дня Сайдкар кладёт причину отказа **в тело ответа**, а `raise_for_status()` печатает только код. Ровно эта обрезанная строка и лежала у 1240 домов в `imv_error_reason` — код без причины. Добавлен общий разбор тела на обоих эндпоинтах сайдкара; тип исключения прежний, значит политика повторов не меняется. ## Три предпосылки этой задачи оказались неверны — поправка к тексту выше **1. «403 — auth rejected / quota exceeded» НЕ означает протухшую учётную запись Авито.** В IMV-флоу авторизации нет вообще: это анонимные XHR, без куки и токена. Строка «auth rejected / quota exceeded» — **наш собственный текст**, которым код подписывает любой 401/403. Владельцу по Авито обновлять нечего, и я снимаю это как ложный след (в сводке #2704 соответствующее уточнение внесено). **2. «Валится конкретный путь геокодера A»** — неверно. Геокодер A просто первый из трёх запросов флоу, поэтому падал всегда он. Сломан был транспорт всего флоу. **3. Честность статуса уже была починена** — коммитом `0815319e` 06.08 в 00:29, то есть до начала работы над этой задачей, вместе с тестом `test_zero_saved_with_errors_is_not_done`. Поэтому PR один, а не два. Заодно: задача бежит **раз в 3 дня**, а не раз в сутки (`interval_days: 3`, наследие миграции 206). ## Статус проверки Правка на проде: маркер `_raise_for_sidecar_status` (функции не существовало до диффа) присутствует в живом контейнере `tradein-scraper`, проводка пула — на месте. Контейнер пересоздан, потому что дифф задел `packages/scraper-kit/**`, а этот путь в allowlist есть. **Функционально не проверено:** следующий прогон — `2026-08-08 16:13 UTC`. Прогона после деплоя не было. Это «не проверено», а не «работает» и не «не работает». Задачу оставляю открытой до первого прогона; критерий приёмки — `saved > 0` и исчезновение `NS_ERROR_PROXY_BAD_GATEWAY` из причин. ## Осталось за рамками - `report_ban` на IMV-пути не подключён: 403 от Авито в пул не доезжает. Нужен критерий «бан», а не «любой 403» — отдельная работа. - **`app/services/house_imv_backfill.py` и `product_handlers.py` НЕ входят в scraper-allowlist** деплоя. Правка только в них доехала бы до бэкенда и не доехала до скрапера, который их исполняет. Ещё один довод за #2680.
Author
Collaborator

ЖДЁТ ПРОГОНА. Базовые числа и критерий — записаны ДО факта

Код доехал. Проверено внутри живого tradein-scraper, а не по релизу:

  • app/services/house_imv_backfill.py содержит проводку пула (proxy_provider / use_pool /
    environment) — все три;
  • scraper_kit/browser_fetcher.py содержит _raise_for_sidecar_status (функции не существовало
    до PR #2708);
  • честность статуса (saved=0 при errors>0 → не done) — в product_handlers.py.

Отдельно: тот факт, что правка вообще доехала до скрапера, теперь гарантирован не
совпадением путей, а механизмом — #2679/PR #2680 смержен, allowlist удалён, после деплоя стоит
сверка образов. Оговорка из моего прошлого комментария («эти два файла не входят в
scraper-allowlist») больше не действует: backend/scraper/tgbot сейчас на одном образе
sha256:0121fc83….

Прогона после деплоя не было. Последний — 3231 от 05.08 16:45, то есть до правки.
Следующий — 2026-08-08 16:13 UTC (interval_days: 3).

Состояние ДО прогона (базовая линия, зафиксирована 2026-08-07)

последняя удачная домовая оценка Авито:   2026-07-03 17:21   (35-й день)
последние 8 прогонов:                     saved 0 · errors 30-43 · checked 50

imv_status:  pending 5 936 (был 5 768) · ok 1 668 · transient_error 1 414
             no_params 344 · no_address 217 · error 46

причины отказа в БД (все — с прошлых прогонов, новых не появлялось):
  503 от tradein-browser:3000/fetch-json ........ 1 240
  500 оттуда же ..................................... 83
  403 auth rejected / quota exceeded ................ 31
  All connection attempts failed .................... 28

Критерий приёмки (записан ДО факта)

Прогон 2026-08-08 16:13 UTC:

  1. counters->>'saved' > 0 — хотя бы одна сохранённая оценка;
  2. в новых houses.imv_error_reason не появляется NS_ERROR_PROXY_BAD_GATEWAY;
  3. встречная проверка честности: если saved = 0 при errors > 0, статус прогона обязан быть
    не done — тогда правка честности подтверждена, а транспорт нет, и это два разных вывода.

Задачу оставляю открытой до этого замера. За рамками по-прежнему: report_ban на IMV-пути
не подключён.

## ЖДЁТ ПРОГОНА. Базовые числа и критерий — записаны ДО факта **Код доехал.** Проверено внутри живого `tradein-scraper`, а не по релизу: - `app/services/house_imv_backfill.py` содержит проводку пула (`proxy_provider` / `use_pool` / `environment`) — все три; - `scraper_kit/browser_fetcher.py` содержит `_raise_for_sidecar_status` (функции не существовало до PR #2708); - честность статуса (`saved=0 при errors>0` → не `done`) — в `product_handlers.py`. Отдельно: тот факт, что правка **вообще** доехала до скрапера, теперь гарантирован не совпадением путей, а механизмом — #2679/PR #2680 смержен, allowlist удалён, после деплоя стоит сверка образов. Оговорка из моего прошлого комментария («эти два файла не входят в scraper-allowlist») больше не действует: backend/scraper/tgbot сейчас на одном образе `sha256:0121fc83…`. **Прогона после деплоя не было.** Последний — 3231 от **05.08 16:45**, то есть до правки. Следующий — **2026-08-08 16:13 UTC** (`interval_days: 3`). ## Состояние ДО прогона (базовая линия, зафиксирована 2026-08-07) ``` последняя удачная домовая оценка Авито: 2026-07-03 17:21 (35-й день) последние 8 прогонов: saved 0 · errors 30-43 · checked 50 imv_status: pending 5 936 (был 5 768) · ok 1 668 · transient_error 1 414 no_params 344 · no_address 217 · error 46 причины отказа в БД (все — с прошлых прогонов, новых не появлялось): 503 от tradein-browser:3000/fetch-json ........ 1 240 500 оттуда же ..................................... 83 403 auth rejected / quota exceeded ................ 31 All connection attempts failed .................... 28 ``` ## Критерий приёмки (записан ДО факта) Прогон **2026-08-08 16:13 UTC**: 1. `counters->>'saved' > 0` — хотя бы одна сохранённая оценка; 2. в новых `houses.imv_error_reason` **не появляется** `NS_ERROR_PROXY_BAD_GATEWAY`; 3. встречная проверка честности: если `saved = 0` при `errors > 0`, статус прогона обязан быть **не** `done` — тогда правка честности подтверждена, а транспорт нет, и это два разных вывода. Задачу оставляю открытой до этого замера. За рамками по-прежнему: `report_ban` на IMV-пути не подключён.
Author
Collaborator

ЗАКРЫТО — оживлено, прод-верифицировано числом

Критерий приёмки был saved > 0. Прогон house_imv_backfill 3467 от 2026-08-08 16:14:

{"saved": 22, "errors": 3, "checked": 50, "skipped": 25}

22 сохранённых — первые с 2026-07-03, после 34 суток ровных нулей. Контраст на границе фикса, дословно из scrape_runs:

3467 | 08-08 16:14 | saved 22 | errors 3    ← ожил
3231 | 08-05 16:45 | saved 0  | errors 35
2996 | 08-02 16:41 | saved 0  | errors 35
2900 | 08-01 16:54 | saved 0  | errors 35
... восемь прогонов подряд 0/35 ...

Независимое подтверждение по таблице (не по счётчику прогона): houses.last_imv_attempt_at > 2026-08-08 AND imv_status='ok' = 22. Оценки реально записаны, а не только заявлены в логе.

Распределение статусов сейчас: ok 1650, pending 5475, transient_error 1389, no_params 362, error 46. То есть путь снова работает, ошибки упали с 35/50 до 3/50.

Чем оживлено — цепочкой, а не одним PR. На задачу ссылались #2708 (домовая оценка ходит в сайдкар через пул, а не через чужой env-прокси), #2637 (браузерный путь Авито подключён к пулу), #2739 (серия отказов обрывается и называет причину). Все три смержены 05–06.08; первый прогон после них (3467, 08.08) и дал 22. Приписывать одному PR не буду — сработала связка «сайдкар + пул прокси».

Осталось не как дефект, а как обычная работа: 5475 домов в pending (ещё не доходили руки, такт задачи не покрывает всех за раз) и 1389 transient_error (ретраятся). Это нормальный ход, а не поломка — сторож #2703 теперь честно пометит нулевой прогон failed, если путь снова ляжет.

Закрываю. Часть эпика #2674.

## ЗАКРЫТО — оживлено, прод-верифицировано числом Критерий приёмки был `saved > 0`. Прогон `house_imv_backfill` **3467** от 2026-08-08 16:14: ``` {"saved": 22, "errors": 3, "checked": 50, "skipped": 25} ``` **22 сохранённых** — первые с 2026-07-03, после **34 суток** ровных нулей. Контраст на границе фикса, дословно из `scrape_runs`: ``` 3467 | 08-08 16:14 | saved 22 | errors 3 ← ожил 3231 | 08-05 16:45 | saved 0 | errors 35 2996 | 08-02 16:41 | saved 0 | errors 35 2900 | 08-01 16:54 | saved 0 | errors 35 ... восемь прогонов подряд 0/35 ... ``` Независимое подтверждение по таблице (не по счётчику прогона): `houses.last_imv_attempt_at > 2026-08-08 AND imv_status='ok'` = **22**. Оценки реально записаны, а не только заявлены в логе. Распределение статусов сейчас: `ok` 1650, `pending` 5475, `transient_error` 1389, `no_params` 362, `error` 46. То есть путь снова работает, ошибки упали с 35/50 до 3/50. **Чем оживлено — цепочкой, а не одним PR.** На задачу ссылались #2708 (домовая оценка ходит в сайдкар через пул, а не через чужой env-прокси), #2637 (браузерный путь Авито подключён к пулу), #2739 (серия отказов обрывается и называет причину). Все три смержены 05–06.08; первый прогон после них (3467, 08.08) и дал 22. Приписывать одному PR не буду — сработала связка «сайдкар + пул прокси». Осталось не как дефект, а как обычная работа: 5475 домов в `pending` (ещё не доходили руки, такт задачи не покрывает всех за раз) и 1389 `transient_error` (ретраятся). Это нормальный ход, а не поломка — сторож #2703 теперь честно пометит нулевой прогон `failed`, если путь снова ляжет. Закрываю. Часть эпика #2674.
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#2698
No description provided.