fix(tradein/dedup): остаток схлопывания домов становится измеряемым числом, а не оценкой (#2690) #2820
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#2820
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2690-dedup-residual"
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
#2690 п.2 (ключ) и п.3 (правило выбора победителя). Кода в ключе и в страже не тронуто —
менять оказалось нечего, и это измеренный вывод, а не пауза.
п.3 — дефект уже исправлен. Задача говорит, что «сортировка ставит дом без объявлений
первым». На актуальном коде это неверно:
listing_cnt DESC NULLS LASTживёт в_KEEPER_ORDERс
1a577fe7(#2674, 06.08 00:11 UTC), в проде подтверждено чтением кода из контейнера.Проверено задним числом по журналу
house_merge_log— 821 слияние прогона 08.08:Ловушка замера, вынесенная в комментарий кода:
listings.scraped_atдля «что было у победителядо слияния» не годится — #2206 двигает его при каждом ре-подтверждении живого листинга,
и по нему получается 207 несуществующих «худших победителей». Честные базы — снимок
listings_snapshotsдо даты слияния и монотонныйlistings.id; обе дают 0.п.2 — независимого наблюдения нет ни одного. Проверены все поля
houses, не предположены:кадастр (2648 заполнено, все различны, все от DaData по нашему же адресу), ФИАС (3678, все
различны), ГАР-guid (441 из 458 пар делят канон), ЖКХ-guid (ставится
WHERE gar_house_guid = …,т.е. это тот же ГАР-guid у 4268 из 4663; 193 из 194 «добавочных» пар приходят кадастровым
KNN-фолбэком), portal-id'ы (различны по построению), координаты (наблюдение, но не идентичность
— уже работают стражем), год+этажность (ложный свидетель: совпадают у 306 пар, отвергнутых
стражем дальше 250 м, и лишь у 18 из 391, где страж молчит).
Что вместо ключа. Остаток фиксируется числом, которое не протухает: перепись после обоих
проходов пишет в
countersпрогона, сколько однокононных строк осталось и ПОЧЕМУ. Разовый замерживёт недолго — «781 лишняя строка» из шапки задачи через четыре дня стала 963.
Корзины намеренно не складываются в один «остаток» — «страж молчит» и «страж отверг» это
противоположные факты:
residual_rows/residual_listingsresidual_no_geom— страж молчит (нет координат у стороны)residual_far— страж отверг по существу (>250 м, медиана 1084 м) → это не дублиresidual_cross_fias— разные ФИАС, заведомо разные зданияresidual_mergeable— прошло все стражи и не слилось → растяжка, ожидание 0Гео-ограждение 250 м не тронуто. Расшивка уже слитого не предлагается.
Test plan
pytest tests/test_house_dedup_merge.py— 42 passed, 5 skipped (live-DB self-skip)test_scraper_kit_scheduler_parity,test_scraper_adapters_contracts,tasks/test_backfill_house_coords_from_listings— 80 passedorigin/main(
KeyError: 'residual_rows', нет_RESIDUAL_SQL), остальные 38 там зелёныеruff check+ruff format --check— чисто;scripts/check-migration-lock-timeout.py—✓ блокирующий DDL прикрыт lock_timeout(миграций в PR нет)_RESIDUAL_SQLна боевой БД даётровно то, что независимо намерено вручную —
963 | 1765 | 8 | 326 | 568 | 61house_dedup_merge, пятница 04:15 UTC) —в
scrape_runs.countersдолжны появиться шестьresidual_*; критерий ДО факта:residual_mergeable = 0(проход не оставил своей же работы) иresidual_rows ≈ 902 ± 40(963 − 61 сольются, плюс недельный приток)Refs #2690