feat(tradein-imv): retry with cleaned address + categorize errors #505
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#505
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-imv-retry-cleaned-address"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Estimate
a0a0b820-e8a8-4eee-aa73-0ab3b98ac233→ IMVavailable:falsebecause address contained prefixСклад,which Avito geocoder rejected.Fix
IMVAuthError/IMVTransientErrorexceptions for proper categorization (was silent warning)re.sub(r"(Склад|Гараж|Подсобка|Нежилое|Помещение|Цех),\s*", "", addr)scripts/probe-imv-by-address.pyfor VPS-side diagnosisRoadmap
PR 5 of 8 —
[[Decision_TradeIn_DataQuality_8PR_Roadmap]].Deep Code Review — verdict APPROVE
Summary
available:falseдля адресов с префиксамиСклад,/Гараж,/ etc + типизация error categorizationRetry logic correctness — OK
_get_or_fetch_imv_cached(estimator.py:220-266): catchIMVAddressNotFoundError→cleaned = _NOISE_PREFIX_RE.sub("", address)→ guardif cleaned != address(исключает бесконечную попытку на already-clean адресах) → ровно один retry черезevaluate_via_imv(cleaned, ...).except IMVAddressNotFoundErrorпадает вreturn Noneбез рекурсии — повторная очистка уже очищенного адреса невозможна, т.к. retry зовётevaluate_via_imvнапрямую, а не_get_or_fetch_imv_cached.Error categorization mapping — OK
_raise_for_status_categorized: 401/403 →IMVAuthError· ≥500 →IMVTransientError· network/timeout (черезtry/exceptвокругsession.get/post) →IMVTransientError.IMVAuthError(estimator.py:256) →logger.error+ None — корректный сигнал «требует human attention».IMVTransientError(estimator.py:261) →logger.warning+ None — комментарий «skipping retry in estimator context» явно объясняет policy decision (estimator не блокирующий).IMVAddressNotFoundError→IMVAuthError→IMVTransientError→Exception) — корректный, нет shadow capture.Cross-file impact
admin.py:511-527(POST /scrape/avito-imvdebug endpoint) импортируетevaluate_via_imv. После PR может броситьIMVAuthError/IMVTransientError— оба попадают в существующийexcept Exception→ HTTP 502. Behavior preserved, но категория ошибки в логе теперь информативнее (logger.exceptionсохранит traceback с типом). Не блокер.tests/test_estimator_imv_integration.py,tests/test_avito_imv_parse.py— ничего не сломано (новые exceptions optional,evaluate_via_imvAPI не меняется).IMVCityMismatchErrorопределён но нигде не raise/catch — pre-existing dead code, не вводится этим PR.Edge cases
_NOISE_PREFIX_REтребует запятую после префикса → «ул. Складская» НЕ ложно-срабатывает (no false-positive clip).re.IGNORECASEкорректно ловит «склад,» / «Склад,» / «СКЛАД,».re.compile— без warm-up cost на каждый estimate.Vault cross-ref
imv_lookup_success_rateметрика в/cache-statsне реализована. Можно отдельным follow-up PR; не блокер для merge т.к. logging уже categorized.imv-benchmarkдля целевого UUID возвращаетavailable:true» можно проверить только post-deploy через probe-script. План OK.Minor observations (non-blocking)
resp.raise_for_status()→ standardHTTPStatusError→ caught byexcept Exception→ silent None. Pre-existing behavior, не введено этим PR; в Avito-контексте может быть полезно отдельно типизировать какIMVRateLimitError(future enhancement).scripts/probe-imv-by-address.py): дублирует regex pattern из estimator.py. Для diagnostic утилиты приемлемо (no shared module overhead), но при будущем расширении списка префиксов придётся синхронизировать оба места.address[:60]— корректно обрезают для compactness без leak полного адреса.Positive
if cleaned != address— defensive correctness против infinite loop.from excсохраняет original cause в traceback.IMVAddressNotFoundError(известный outcome) vsException(unexpected) — корректное разделение «expected miss» / «error to log»._NOISE_PREFIX_REобъясняет почему именно эти префиксы (Avito-геокодер не распознаёт нежилые назначения).Verdict
Merge ready. Per [Auto-merge any scope] (2026-05-16): squash + delete branch.