(medium) house_imv_backfill.py/_process_one_house: IMV вернул price=0 → дом помечается imv_status='ok' и больше не переоценивается #1524

Closed
opened 2026-06-15 05:59:14 +00:00 by bot-backend · 1 comment
Collaborator

Severity: medium · Категория: data-integrity · Файл: tradein-mvp/backend/app/services/house_imv_backfill.py:581-609

house_imv_backfill.py:581-609 — evaluate_via_imv при найденном адресе, но отсутствии рыночной цены возвращает IMVEvaluation с recommended_price=0 (avito_imv.py:327 'recommendedPrice or 0', комментарий 324 прямо говорит, что 0 = 'нет оценки'). _process_one_house любой успешный возврат трактует как 'ok': нет проверки eval_result.recommended_price>0 / market_count перед save_imv_result; затем _mark_status ставит imv_status='ok' (строка 302). Downstream backfill_house_imv (WHERE imv_status='pending', строка 392) и process_houses_imv_batch (WHERE COALESCE(imv_status,'pending') != 'ok', строка 498) такие дома навсегда пропускают; estimator.py:873 фильтрует recommended_price>0, т.е. оценки фактически нет. Импакт: дом с нулевой/пустой оценкой залипает в 'ok' и никогда не ретраится — тихая дыра в покрытии IMV. Чинить: при recommended_price<=0 (или market_count в [None,0]) выставлять статус not_found/no_market вместо 'ok', чтобы дом попадал в ретрай.

Почему баг: В avito_imv.py:327 recommended_price = price_block.get('recommendedPrice') or 0 — отсутствие цены отдаётся как 0, а не как ошибка. В _process_one_house нет проверки eval_result.recommended_price>0 / market_count перед save_imv_result + 'ok'. Downstream-потребители (estimator.py:873 'AND recommended_price > 0', trade_in.py:276 truthy-guard) 0 отфильтровывают, что подтверждает: 0 — это 'нет оценки', но статус 'ok' блокирует повторную попытку.

Как чинить: Если eval_result.recommended_price <= 0 (или market_count == 0) — не помечать 'ok', а ставить, например, 'not_found'/'no_market' с last_imv_attempt_at, чтобы дом мог быть переоценён при следующем наполнении рынка.


deep-audit «армия ботов 2» · verify+harden, confidence 0.85 · unit U126

**Severity:** medium · **Категория:** data-integrity · **Файл:** `tradein-mvp/backend/app/services/house_imv_backfill.py:581-609` house_imv_backfill.py:581-609 — evaluate_via_imv при найденном адресе, но отсутствии рыночной цены возвращает IMVEvaluation с recommended_price=0 (avito_imv.py:327 'recommendedPrice or 0', комментарий 324 прямо говорит, что 0 = 'нет оценки'). _process_one_house любой успешный возврат трактует как 'ok': нет проверки eval_result.recommended_price>0 / market_count перед save_imv_result; затем _mark_status ставит imv_status='ok' (строка 302). Downstream backfill_house_imv (WHERE imv_status='pending', строка 392) и process_houses_imv_batch (WHERE COALESCE(imv_status,'pending') != 'ok', строка 498) такие дома навсегда пропускают; estimator.py:873 фильтрует recommended_price>0, т.е. оценки фактически нет. Импакт: дом с нулевой/пустой оценкой залипает в 'ok' и никогда не ретраится — тихая дыра в покрытии IMV. Чинить: при recommended_price<=0 (или market_count в [None,0]) выставлять статус not_found/no_market вместо 'ok', чтобы дом попадал в ретрай. **Почему баг:** В avito_imv.py:327 recommended_price = price_block.get('recommendedPrice') or 0 — отсутствие цены отдаётся как 0, а не как ошибка. В _process_one_house нет проверки eval_result.recommended_price>0 / market_count перед save_imv_result + 'ok'. Downstream-потребители (estimator.py:873 'AND recommended_price > 0', trade_in.py:276 truthy-guard) 0 отфильтровывают, что подтверждает: 0 — это 'нет оценки', но статус 'ok' блокирует повторную попытку. **Как чинить:** Если eval_result.recommended_price <= 0 (или market_count == 0) — не помечать 'ok', а ставить, например, 'not_found'/'no_market' с last_imv_attempt_at, чтобы дом мог быть переоценён при следующем наполнении рынка. --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.85 · unit U126</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:59:14 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:02:18 +00:00
Owner

🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)

Текущее состояние кода: tradein-mvp/backend/app/services/house_imv_backfill.py:581-609 (_process_one_house). evaluate_via_imv вызывается на :582; при успехе → save_imv_result(db, hid, params, eval_result) (:598) + db.commit() (:599) → return "ok" (:609). Метку «ok» ставит save_imv_result (UPDATE imv_status='ok' на :298-308).

Корень: В scrapers/avito_imv.py:327 recommended_price = price_block.get("recommendedPrice") or 0 — отсутствие рыночной цены отдаётся как 0 (комментарий :324: «Отсутствующие цены → 0 (caller трактует как нет оценки)»). В _process_one_house НЕТ проверки eval_result.recommended_price > 0 / market_count перед save+ok: любой успешный возврат (включая recommended_price=0) трактуется как «ok». Downstream-потребители 0 отфильтровывают — estimator.py фильтрует recommended_price > 0, а ретрай-выборки пропускают «ok»-дома (WHERE imv_status = 'pending' на :392; WHERE COALESCE(imv_status,'pending') != 'ok' на :498). Итог: дом с нулевой/пустой оценкой залипает в «ok» и никогда не переоценивается — тихая дыра в покрытии IMV.

Что править:

  • В _process_one_house перед save+«ok» проверять eval_result.recommended_price > 0 (и/или market_count не в [None, 0]). Если ≤ 0 — выставлять статус not_found/no_market через _mark_status (:311, ставит last_imv_attempt_at = NOW()), чтобы дом попадал в ретрай при наполнении рынка, а не в «ok».
  • NB: market_count приходит как count (avito_imv.py:330, тип int | None) — учитывать None при проверке.

Что посмотреть:

  • Код: house_imv_backfill.py:581-609 (_process_one_house), :298-308 («ok»-UPDATE внутри save_imv_result), :311-336 (_mark_status), :392, 498 (ретрай-выборки); scrapers/avito_imv.py:324-331 (recommendedPrice or 0, count). Тест: house с recommended_price=0 → статус ≠ 'ok', попадает в следующий backfill-проход.
  • Vault: релевантных заметок не найдено (house_imv_backfill imv_status ok recommended_price retry — пусто).
**🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)** **Текущее состояние кода:** `tradein-mvp/backend/app/services/house_imv_backfill.py:581-609` (`_process_one_house`). `evaluate_via_imv` вызывается на :582; при успехе → `save_imv_result(db, hid, params, eval_result)` (:598) + `db.commit()` (:599) → `return "ok"` (:609). Метку «ok» ставит `save_imv_result` (UPDATE `imv_status='ok'` на :298-308). **Корень:** В `scrapers/avito_imv.py:327` `recommended_price = price_block.get("recommendedPrice") or 0` — отсутствие рыночной цены отдаётся как `0` (комментарий :324: «Отсутствующие цены → 0 (caller трактует как нет оценки)»). В `_process_one_house` НЕТ проверки `eval_result.recommended_price > 0` / `market_count` перед save+`ok`: любой успешный возврат (включая `recommended_price=0`) трактуется как «ok». Downstream-потребители 0 отфильтровывают — estimator.py фильтрует `recommended_price > 0`, а ретрай-выборки пропускают «ok»-дома (`WHERE imv_status = 'pending'` на :392; `WHERE COALESCE(imv_status,'pending') != 'ok'` на :498). Итог: дом с нулевой/пустой оценкой залипает в «ok» и никогда не переоценивается — тихая дыра в покрытии IMV. **Что править:** - В `_process_one_house` перед save+«ok» проверять `eval_result.recommended_price > 0` (и/или `market_count` не в [None, 0]). Если ≤ 0 — выставлять статус `not_found`/`no_market` через `_mark_status` (:311, ставит `last_imv_attempt_at = NOW()`), чтобы дом попадал в ретрай при наполнении рынка, а не в «ok». - NB: `market_count` приходит как `count` (avito_imv.py:330, тип `int | None`) — учитывать None при проверке. **Что посмотреть:** - Код: `house_imv_backfill.py:581-609` (`_process_one_house`), `:298-308` («ok»-UPDATE внутри save_imv_result), `:311-336` (`_mark_status`), `:392, 498` (ретрай-выборки); `scrapers/avito_imv.py:324-331` (`recommendedPrice or 0`, `count`). Тест: house с `recommended_price=0` → статус ≠ 'ok', попадает в следующий backfill-проход. - Vault: релевантных заметок не найдено (`house_imv_backfill imv_status ok recommended_price retry` — пусто).
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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#1524
No description provided.