[HIGH] tradein: ночное геокодирование даёт 0 сохранённых 8 прогонов подряд — очередь на 98% забита неактивными объявлениями чужих регионов #2604

Closed
opened 2026-07-31 21:57:14 +00:00 by lekss361 · 2 comments
Owner

Найдено 2026-08-01 при проверке эффекта от #2601. Ночная задача geocode_missing_listings работает вхолостую минимум с 24 июля — восемь прогонов подряд с нулём сохранённых.

Факты

 id  |  status | started             | checked | saved | skipped
2755 | done    | 2026-07-31 01:35:36 |   592   |   0   |  592
2690 | done    | 2026-07-30 04:53:25 |   377   |   0   |  377
2666 | done    | 2026-07-29 22:20:04 |   400   |   0   |  400
2526 | done    | 2026-07-28 03:19:25 |   564   |   0   |  564
2436 | done    | 2026-07-27 00:44:47 |   329   |   0   |  329
2339 | done    | 2026-07-25 18:02:01 |   400   |   0   |  400
2198 | done    | 2026-07-24 01:08:42 |   592   |   0   |  592

Каждый прогон идёт 30-50 минут при лимите Nominatim 1 запрос/сек — то есть бюджет расходуется полностью и впустую.

Причина

Выборка задачи (app/tasks/geocode_missing.py) фильтрует по lat IS NULL, длине адреса и backoff'у geocode_tried_at, но не фильтрует is_active. В очереди:

строк
всего в очереди 14294
из них is_active = false 14074 (98,5%)
активных (реальная работа) 220

Неактивные — это объявления чужих регионов, у которых адрес состоит только из региона и города, без улицы и дома:

Новосибирская обл.,Новосибирск     — 214
Тюменская обл.,Тюмень              — 207
Татарстан, Казань                  — 197
Омская обл.,Омск                   — 195
Челябинская обл.,Челябинск         — 184
Удмуртская Республика,Ижевск       — 165
Ростовская обл.,Ростов-на-Дону     — 157
…

13693 из 14294 строк очереди вообще не содержат ни одной цифры — дома в адресе нет. Геокодер честно возвращает None (fail-closed гейт #2589 правильно отказывается достраивать неизвестный топоним), результат — saved=0.

Хуже того, сортировка ORDER BY listings_count DESC ставит именно этот мусор в начало очереди: у «Новосибирская обл.,Новосибирск» 214 объявлений, у любого реального адреса — 1-2. Бюджет съедается сверху вниз, до настоящих адресов очередь не доходит никогда.

Откуда взялись чужие города

всего avito-объявлений       44636
активных                       243
из наших 6 городов           27724
из ЧУЖИХ городов             16912   ← 1629 различных слагов

Собраны почти все одним днём: 2026-06-18 — 15207 строк, 1629 различных городов (+1247 от 31 мая, +458 от 19-20 июня). Похоже на неограниченный проход avito_full_load / newbuilding-развёртки без гео-фильтра.

Отдельный дефект: у всех 16912 проставлен region_code = 66 (Свердловская обл.), хотя это Новосибирск, Казань, Челябинск и далее. Сейчас урона нет — все неактивны, — но любой будущий запрос вида «всё по региону 66» получит их в выборку. Мина замедленного действия.

Что делать

1. Фильтр is_active в выборке (главное, ~1 строка). Срежет очередь с 14294 до 220 и задача наконец начнёт делать полезную работу. Мёртвое объявление чужого региона геокодировать незачем ни при каких обстоятельствах.

2. Починить region_code у 16912 строк — либо проставить настоящий регион, либо, если они не нужны, деактивировать по-честному с пометкой источника ошибки. Требует решения: нужны ли эти данные вообще (как рыночный фон они бесполезны — без улицы и дома их нельзя ни к чему привязать).

3. Проверить, откуда льются чужие города, и закрыть канал: avito_full_load / avito_full_load_exhaustive / avito_newbuilding_sweep. В #2598 гео-гейт _parse_html (kept_slug, avito_serp_ekb_only) уже есть для городских развёрток — надо понять, почему полные загрузки его не применяют.

Связь с текущим эпиком

Это объясняет, почему проставление города (#2598) и передача city_hint (#2601) пока не дают видимого эффекта: механизм, который должен ими пользоваться, простаивает. После фильтра is_active эти 220 активных строк (все avito, город в колонке пока NULL) станут реальной проверкой всей цепочки.

Связано: #2594, #2576, #2583, #2589.

Найдено 2026-08-01 при проверке эффекта от #2601. Ночная задача `geocode_missing_listings` работает вхолостую **минимум с 24 июля** — восемь прогонов подряд с нулём сохранённых. ## Факты ``` id | status | started | checked | saved | skipped 2755 | done | 2026-07-31 01:35:36 | 592 | 0 | 592 2690 | done | 2026-07-30 04:53:25 | 377 | 0 | 377 2666 | done | 2026-07-29 22:20:04 | 400 | 0 | 400 2526 | done | 2026-07-28 03:19:25 | 564 | 0 | 564 2436 | done | 2026-07-27 00:44:47 | 329 | 0 | 329 2339 | done | 2026-07-25 18:02:01 | 400 | 0 | 400 2198 | done | 2026-07-24 01:08:42 | 592 | 0 | 592 ``` Каждый прогон идёт 30-50 минут при лимите Nominatim 1 запрос/сек — то есть бюджет расходуется полностью и впустую. ## Причина Выборка задачи (`app/tasks/geocode_missing.py`) фильтрует по `lat IS NULL`, длине адреса и backoff'у `geocode_tried_at`, но **не фильтрует `is_active`**. В очереди: | | строк | |---|---| | всего в очереди | 14294 | | из них `is_active = false` | **14074 (98,5%)** | | активных (реальная работа) | **220** | Неактивные — это объявления **чужих регионов**, у которых адрес состоит только из региона и города, без улицы и дома: ``` Новосибирская обл.,Новосибирск — 214 Тюменская обл.,Тюмень — 207 Татарстан, Казань — 197 Омская обл.,Омск — 195 Челябинская обл.,Челябинск — 184 Удмуртская Республика,Ижевск — 165 Ростовская обл.,Ростов-на-Дону — 157 … ``` 13693 из 14294 строк очереди вообще **не содержат ни одной цифры** — дома в адресе нет. Геокодер честно возвращает `None` (fail-closed гейт #2589 правильно отказывается достраивать неизвестный топоним), результат — `saved=0`. Хуже того, сортировка `ORDER BY listings_count DESC` ставит именно этот мусор **в начало очереди**: у «Новосибирская обл.,Новосибирск» 214 объявлений, у любого реального адреса — 1-2. Бюджет съедается сверху вниз, до настоящих адресов очередь не доходит никогда. ## Откуда взялись чужие города ``` всего avito-объявлений 44636 активных 243 из наших 6 городов 27724 из ЧУЖИХ городов 16912 ← 1629 различных слагов ``` Собраны почти все одним днём: **2026-06-18 — 15207 строк, 1629 различных городов** (+1247 от 31 мая, +458 от 19-20 июня). Похоже на неограниченный проход `avito_full_load` / newbuilding-развёртки без гео-фильтра. **Отдельный дефект: у всех 16912 проставлен `region_code = 66`** (Свердловская обл.), хотя это Новосибирск, Казань, Челябинск и далее. Сейчас урона нет — все неактивны, — но любой будущий запрос вида «всё по региону 66» получит их в выборку. Мина замедленного действия. ## Что делать **1. Фильтр `is_active` в выборке (главное, ~1 строка).** Срежет очередь с 14294 до 220 и задача наконец начнёт делать полезную работу. Мёртвое объявление чужого региона геокодировать незачем ни при каких обстоятельствах. **2. Починить `region_code`** у 16912 строк — либо проставить настоящий регион, либо, если они не нужны, деактивировать по-честному с пометкой источника ошибки. Требует решения: нужны ли эти данные вообще (как рыночный фон они бесполезны — без улицы и дома их нельзя ни к чему привязать). **3. Проверить, откуда льются чужие города,** и закрыть канал: `avito_full_load` / `avito_full_load_exhaustive` / `avito_newbuilding_sweep`. В #2598 гео-гейт `_parse_html` (`kept_slug`, `avito_serp_ekb_only`) уже есть для городских развёрток — надо понять, почему полные загрузки его не применяют. ## Связь с текущим эпиком Это объясняет, почему проставление города (#2598) и передача `city_hint` (#2601) пока не дают видимого эффекта: механизм, который должен ими пользоваться, простаивает. После фильтра `is_active` эти 220 активных строк (все avito, город в колонке пока NULL) станут реальной проверкой всей цепочки. Связано: #2594, #2576, #2583, #2589.
Author
Owner

Диагноз по пункту 3 — канал уже закрыт, править нечего.

Гео-фильтр карточек (avito_serp_ekb_only в _parse_html) появился 2026-06-20, коммит f0264237 «per-card ЕКБ гео-фильтр (отсечь padding по России)». Он отбрасывает карточки, чей city-слаг в URL не совпадает с городом-целью, оставляя только безслаговые (консервативно).

Сверяем с датами сбора чужих городов:

день строк различных городов
2026-05-31 1247 40
2026-06-18 15207 1629
2026-06-19 142 37
2026-06-20 316 117

Всё до фильтра. После 20 июня — ни одной новой строки чужого города. То есть массовый залив 18 июня был последним; текущие развёртки чистые, и то, что сегодняшние 243 активных объявления Авито все из наших городов, это подтверждает.

Значит из issue остаются только два пункта, оба про исторические данные:

  • пункт 1 (фильтр is_active в очереди геокодирования) — PR #2605, на ревью;
  • пункт 2 (region_code = 66 у 16912 чужих строк) — чисто разгребание накопленного. Все они неактивны, влияния на оценки нет. Требует решения владельца: проставить настоящий регион или удалить как бесполезные — без улицы и дома их всё равно не к чему привязать, рыночным фоном они служить не могут.

Пункт 3 закрываю как неактуальный.

Диагноз по пункту 3 — **канал уже закрыт, править нечего**. Гео-фильтр карточек (`avito_serp_ekb_only` в `_parse_html`) появился 2026-06-20, коммит `f0264237` «per-card ЕКБ гео-фильтр (отсечь padding по России)». Он отбрасывает карточки, чей city-слаг в URL не совпадает с городом-целью, оставляя только безслаговые (консервативно). Сверяем с датами сбора чужих городов: | день | строк | различных городов | |---|---|---| | 2026-05-31 | 1247 | 40 | | 2026-06-18 | **15207** | **1629** | | 2026-06-19 | 142 | 37 | | 2026-06-20 | 316 | 117 | Всё до фильтра. **После 20 июня — ни одной новой строки чужого города.** То есть массовый залив 18 июня был последним; текущие развёртки чистые, и то, что сегодняшние 243 активных объявления Авито все из наших городов, это подтверждает. Значит из issue остаются только два пункта, оба про исторические данные: - **пункт 1** (фильтр `is_active` в очереди геокодирования) — PR #2605, на ревью; - **пункт 2** (`region_code = 66` у 16912 чужих строк) — чисто разгребание накопленного. Все они неактивны, влияния на оценки нет. Требует решения владельца: проставить настоящий регион или удалить как бесполезные — без улицы и дома их всё равно не к чему привязать, рыночным фоном они служить не могут. Пункт 3 закрываю как неактуальный.
Author
Owner

Закрываю — все три пункта закрыты, каждый проверен на живых данных.

Пункт 1 — фильтр активности в очереди (PR #2605, в проде)

Очередь сократилась с 14294 строк до 179 пар. Ночной прогон geocode_missing_listings id=2886 в 13:18 UTC:

 id  | status |     started (UTC)     | checked | saved | skipped
2886 | done   | 2026-08-01 13:18:39   |   229   |  393  |   98    ← после фикса
2755 | done   | 2026-07-31 01:35:35   |   592   |   0   |  592
2690 | done   | 2026-07-30 04:53:25   |   377   |   0   |  377

393 объявления получили координаты — первый ненулевой результат после восьми ночей подряд с нулём.

Пункт 2 — ложный region_code (PR #2612, в проде)

Миграция 200 применилась, сверка после применения:

проверка ожидалось получено
чужие города → NULL 16930 16930
наши шесть городов сохранили 66 28542 28542
чужих с 66 не осталось 0 0
другие источники не задеты без изменений cian 20325, domklik 6592, yandex 15418, n1 382 — все 66

Выбран NULL, а не настоящий регион: выводить его из текста адреса для мусорных данных смысла нет, честное «неизвестно» лучше ложной шестьдесят шестой. Строки не удалялись — если понадобятся, они на месте.

Уточнение к моему разбору: я писал, что listings.region_code не читает никто. Это было неточно — ревью нашло живого читателя, app/services/yandex_address_backfill.py:82 фильтрует по region_code = 66. Обошлось: он скоупится на source='yandex', а миграция трогает только source='avito', пересечение пустое. Но при будущих правках region_code за пределами Авито этот файл надо учитывать явно.

Пункт 3 — канал уже был закрыт

Гео-фильтр карточек (avito_serp_ekb_only) появился 2026-06-20 коммитом f0264237. Весь залив чужих городов — 18 июня (15207 строк, 1629 городов) плюс хвосты 31 мая и 19-20 июня. После 20 июня ни одной новой строки чужого города. Правки не требовалось.

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

Строки не удалены — только обезврежена метка. Вопрос «нужны ли 16930 неактивных объявлений чужих регионов вообще» остаётся открытым, но перестал быть срочным: вреда они больше не несут, из очереди геокодирования исключены фильтром активности, ложным регионом не притворяются.

Связанное, найденное по ходу: #2607 (соседняя молча неработающая ночная задача), #2613 (шесть из семи запасных прокси мертвы).

✅ **Закрываю — все три пункта закрыты, каждый проверен на живых данных.** ## Пункт 1 — фильтр активности в очереди (PR #2605, в проде) Очередь сократилась с 14294 строк до 179 пар. Ночной прогон `geocode_missing_listings` id=2886 в 13:18 UTC: ``` id | status | started (UTC) | checked | saved | skipped 2886 | done | 2026-08-01 13:18:39 | 229 | 393 | 98 ← после фикса 2755 | done | 2026-07-31 01:35:35 | 592 | 0 | 592 2690 | done | 2026-07-30 04:53:25 | 377 | 0 | 377 ``` **393 объявления получили координаты** — первый ненулевой результат после восьми ночей подряд с нулём. ## Пункт 2 — ложный `region_code` (PR #2612, в проде) Миграция 200 применилась, сверка после применения: | проверка | ожидалось | получено | |---|---|---| | чужие города → `NULL` | 16930 | **16930** ✅ | | наши шесть городов сохранили 66 | 28542 | **28542** ✅ | | чужих с 66 не осталось | 0 | **0** ✅ | | другие источники не задеты | без изменений | cian 20325, domklik 6592, yandex 15418, n1 382 — все 66 ✅ | Выбран `NULL`, а не настоящий регион: выводить его из текста адреса для мусорных данных смысла нет, честное «неизвестно» лучше ложной шестьдесят шестой. Строки не удалялись — если понадобятся, они на месте. Уточнение к моему разбору: я писал, что `listings.region_code` не читает никто. **Это было неточно** — ревью нашло живого читателя, `app/services/yandex_address_backfill.py:82` фильтрует по `region_code = 66`. Обошлось: он скоупится на `source='yandex'`, а миграция трогает только `source='avito'`, пересечение пустое. Но при будущих правках `region_code` за пределами Авито этот файл надо учитывать явно. ## Пункт 3 — канал уже был закрыт Гео-фильтр карточек (`avito_serp_ekb_only`) появился 2026-06-20 коммитом `f0264237`. Весь залив чужих городов — 18 июня (15207 строк, 1629 городов) плюс хвосты 31 мая и 19-20 июня. После 20 июня ни одной новой строки чужого города. Правки не требовалось. ## Что осталось за рамками Строки не удалены — только обезврежена метка. Вопрос «нужны ли 16930 неактивных объявлений чужих регионов вообще» остаётся открытым, но перестал быть срочным: вреда они больше не несут, из очереди геокодирования исключены фильтром активности, ложным регионом не притворяются. Связанное, найденное по ходу: #2607 (соседняя молча неработающая ночная задача), #2613 (шесть из семи запасных прокси мертвы).
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#2604
No description provided.