feat(tradein): ручка «дома, уехавшие от собственных объявлений» (#2996) #3010
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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#3010
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2996-mislocated-houses-watchdog"
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?
Закрывает часть Находки 3 из #2996 — не гардом на приёме, а сторожем, который переживёт выход в Москву. Полный разбор с числами — в комментарии к #2996.
Что нашлось сверх постановки
Постановка говорила: «23 дома лежат вне области 66, гарда на приёме нет». Подтвердилось, плюс два недостающих куска.
Масштаб. К этим домам привязано 591 объявление. Адреса екатеринбургские («Ул. 8 Марта», «Крауля», «Амундсена»), координаты — Варшава, Белград, Таллин, Владивосток, Ижевск.
Причина. 22 из 23 несут в
raw_payloadодин и тот же след:Разовый бэкфилл 27.05 звал Yandex-геокодер напрямую, без резолва города. Живой путь при этом чист — проверил обе напрашивавшиеся гипотезы, и обе не подтвердились:
Скрипта в репозитории нет — он не повторится сам. Значит гард нужен не столько живому пути, сколько следующему разовому скрипту: тот обошёл живую защиту, потому что звал API напрямую.
17 из 22 помечены
precision: "exact". Точность отвечает на «нашёлся ли номер дома», а не «в том ли городе». Как критерий приёмки бэкфилла она бесполезна — все 17 «точных» неверны.Инвариант выбран так, чтобы пережить Москву
Не «дом внутри рамки области», а «дом рядом со своими объявлениями». Рамка сломалась бы ровно при том расширении, ради которого заведена #2996.
Он же строго сильнее: ловит 25 домов против 23 у рамки, и оба лишних проверены вручную — настоящие («Ул. Белинского/Фурманова» за 207 км, 34 объявления).
Порог не подобран на глаз
Замер по 9 052 домам с привязанными объявлениями:
Между 46.7 и 119.2 км нет ни одного дома. Порог 100 лежит в середине пустого промежутка, а не на краю распределения.
Первая редакция была неверной, и её остановил замер
Я сначала добавил счётчик полем в
/scraper/data-quality. Померил цену:17-кратное удорожание опрашиваемой ручки ради числа, которое меняется раз в месяцы. Переделал в отдельную ручку по требованию; на возврат тяжёлого агрегата в горячий путь поставлен контроль-тест.
Пробовал и удешевить: вариант через
min(ST_Distance(...))оказался медленнее (724 мс — расстояние считается на каждую из 88 тыс. строк вместо одного на дом) и при этом ловит на два дома меньше. Индексы поhouse_id_fkесть — 445 мс это честная цена прохода.Ручка отдаёт не только счётчик, но и масштаб: список домов с адресами и числом привязанных объявлений. По одному числу «25» решение об очистке не принять.
Как проверено
origin/mainтри теста красные, краснота везде по значению — ни одного ImportError/AttributeError. Сообщения называют фактическое состояние («порога нет вовсе», «есть ли обработчик: False»).percentile_discи словоmislocatedне должны появляться вget_data_quality.l.house_id_fk = h.id, медиана координат) и не содержать координатной рамкиST_Y(...) BETWEEN— она не переживёт расширение региона.pytest tradein-mvp/backend— 4642 passed, 23 skipped.Что осталось владельцу
Очистка 591 объявления: обнулить координаты 22 домов или удалить дома с пере-сопоставлением. Первое честнее (координат нет), второе чище (дом пересоздастся с правильными). Ручка теперь даёт список, по которому это решение можно принять.