fix(tradein/houses): вернуть координаты объявлений в дом, когда объявления согласны (#2771) #2780
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#2780
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2771-house-coords-from-listings"
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?
Summary
Дом берёт координаты один раз — при создании, из породившего его объявления. Объявление геокодируется позже (
geoportal_coords_backfill,geocode_missing_listings— обе живые) и пишет вlistings;ON CONFLICTу вставки дома обновляет толькоaddress. Обратно координаты не возвращались.Новая ежедневная задача
house_coords_from_listings(окно 03:00-04:00 UTC — перед недельнымhouse_dedup_merge) берёт для дома сlat IS NULLцентроид geom его объявлений и разброс = maxST_DistanceSphereот центроида до объявления. Разброс <= 125 м → центроид пишется в дом.Что это даёт дедупу. Не «разблокирует слияния». Сейчас гео-ограждение
house_dedup_mergeотбраковывает проигравших с NULL geom, потому что проверить тождество нечем. После переноса у ограждения появляется возможность оценить пару: часть сольётся, часть будет отвергнута правильно (дома в разных городах). Рост числа слияний здесь не обещается и не закладывается.Порог 125 м — откуда
Перемерено на проде 2026-08-07 честно (
ST_DistanceSphere/geography), а не приближением «градусы × 111320». Гистограмма разброса по 258 домам с >1 различной точкой обрыва не даёт: плотное ядро 0-125 м (150 домов), затем ровное плато ~4-5 домов на каждые 25 м вплоть до 400 м, и масса из 67 домов дальше 400 м. Раз в данных порога нет, он взят от потребителя: гео-ограждениеhouse_dedup_merge(#2187) считает два дома одним зданием приST_DistanceSphere <= 250. Записанный центроид — оценка с погрешностью ровно в разброс; отдать ей весь бюджет ограждения значит позволить двум домам разъехаться на 500 м и сломать сравнение. Половина бюджета → 125 м.Решение не несущее: 125 м пропускает 1382 дома, 250 м — 1403. Разница в 21 дом не теряется, а откладывается до следующего прогона.
Замер ДО — тем же SQL, что мержится
_BUILD_CANDIDATES_SQL+_COUNTERS_SQLиз самого модуля, прогнаны на проде read-only (BEGIN/ROLLBACK):Ожидание ПОСЛЕ первого прогона: 7680 → 9062 домов с координатами (79.8% → 94.2%), без координат 1945 → 563.
Пропуск не молчит
Счётчики разделены по причинам (
skipped_no_listings/skipped_no_listing_coords/skipped_scattered/scattered_over_5km/worst_spread_m), а худшие дома с разбросом называются в логе поимённо — иначе усечение читается как «покрыто всё». Разбросанные дома — дефект сопоставителя, вынесен отдельной работой: #2777 (108 домов, 2663 объявления, худший «ул. Кирова,4» — 5 объявлений с радиусом 289.9 км).Test plan
tests/tasks/test_backfill_house_coords_from_listings.py— 8 статических + поведенческий на живом PostGIS: 5 домов, 5 исходов (перенос центроида / пропуск дома с объявлениями в 11 км / объявления без geom / нет объявлений / уже есть координаты — не перезаписаны), второй прогон no-op.origin/main→ImportError: cannot import name 'backfill_house_coords_from_listings'— механизма нет.AND c.spread_m <= ...из UPDATE → дом с объявлениями в 11 км получает середину между двумя городами (56.89) → тест краснеет.ruff check+ruff format,grep -nE ':[a-z_]+::[a-z]'пуст (psycopg v3).Прод-верификация (критерий записан ДО факта)
Задача по расписанию. Ближайший штатный прогон — 03:00-04:00 UTC следующих суток после деплоя; для немедленного смоука
UPDATE scrape_schedules SET next_run_at=now() WHERE source='house_coords_from_listings'(подхват <= 60 с, планировщик вtradein-scraper).Критерий приёмки: после первого прогона
SELECT count(*) FROM houses WHERE lat IS NULL= 563 ± 20 (было 1945), аscrape_runsпоследнего прогона несётupdated ≈ 1382,skipped_scattered = 108,errors = 0. Отдельно: у дома 380628 («ул. Кирова,4»)latостаётся NULL — он обязан быть пропущен.Порядок деплоя безопасен: миграция 239 сеет
next_run_atна завтра 03:00 UTC, поэтому старый образ не встретит источник без handler'а.Closes #2771