fix(db): #1781 backfill listings.house_id_fk from house_sources (cian novostroyki) #1784

Merged
lekss361 merged 1 commit from fix/1781-cian-novostroyki-fk-backfill into main 2026-06-19 14:56:10 +00:00
Collaborator

Closes part of #1781 (the me-safe subset).

Что

data/sql/130_backfill_listings_house_id_fk.sql — одноразовый идемпотентный бэкфилл listings.house_id_fk из канонической house_sources по точному source-id (ext_source=house_source AND ext_id=house_ext_id → house_id).

Зачем

Realtime-зеркало FK (base.py:607-616) появилось только 17.06 (e63b21e). Строки, сматченные в house_sources ДО этого — особенно 9205 cian-новостроек, замороженных на 2026-05-31 — так и остались с house_id_fk=NULL, ломая канонический путь оценщика «тот же дом через house_id_fk» (по городу 93% активных cian-новостроек без FK). Это всплыло при разборе «Евгения Савкова 29» (#1781).

Безопасность

  • Детерминированно: только из существующего матча в house_sources (UNIQUE(ext_source,ext_id) → ≤1 дом на листинг), без адресного fuzzy (063 Step 5 намеренно НЕ повторяется → нет мислинка/фрагментации).
  • Идемпотентно: WHERE house_id_fk IS NULL → повторный прогон = no-op, существующий FK не перетирается.
  • Прод-замер (read-only): 9235/9235 целевых строк резолвятся, 0 нерезолвимых.
  • Семантика 1:1 с realtime-зеркалом — просто применена к беклогу офлайн. Будущие строки линкуются в реальном времени (e63b21e).
  • Применение: миграции монтируются в initdb (filename order) на fresh-init (на пустой БД — безвредный no-op) и вручную через psql на проде. Контракт — идемпотентность, не ledger.

Ревью

code-reviewer APPROVE (join детерминирован, идемпотентность строгая, мислинка нет, конвенция 063/124, GET DIAGNOSTICS корректен, fresh-init без хазарда). Минор: покрывает только листинги с непустыми house_source/house_ext_id (целевая когорта несёт catalog-id 100%) — прочие источники с fallback-ключом вне scope (документировано).

После деплоя

В RAISE NOTICE ожидается filled≈9235 | residual_with_extid=0. Ненулевой WARNING — сигнал к разбору матчинга, не сбой миграции.

НЕ входит (зона Лёхи / prod-exec, см. #1781)

Расширение охвата cian_city_sweep (якоря/радиус/анти-бан) + обновление cian-cookies + точечный ре-скрейп Широкой Речки — без этого свежие cian-объявления дома 29 не подтянутся; этот PR только чинит линковку того, что уже есть. Авто-деактивацию протухших novostroyki (deactivate_stale_cian) — сиквенсить ПОСЛЕ расширения охвата.

Связано: #1774 (PR #1776, estimator Tier A теперь принимает same-building novostroyki).

Closes part of #1781 (the **me-safe** subset). ## Что `data/sql/130_backfill_listings_house_id_fk.sql` — одноразовый идемпотентный бэкфилл `listings.house_id_fk` из канонической `house_sources` по точному source-id (`ext_source=house_source AND ext_id=house_ext_id → house_id`). ## Зачем Realtime-зеркало FK (`base.py:607-616`) появилось только 17.06 (e63b21e). Строки, сматченные в `house_sources` ДО этого — особенно **9205 cian-новостроек, замороженных на 2026-05-31** — так и остались с `house_id_fk=NULL`, ломая канонический путь оценщика «тот же дом через house_id_fk» (по городу 93% активных cian-новостроек без FK). Это всплыло при разборе «Евгения Савкова 29» (#1781). ## Безопасность - **Детерминированно**: только из существующего матча в `house_sources` (UNIQUE(ext_source,ext_id) → ≤1 дом на листинг), без адресного fuzzy (063 Step 5 намеренно НЕ повторяется → нет мислинка/фрагментации). - **Идемпотентно**: `WHERE house_id_fk IS NULL` → повторный прогон = no-op, существующий FK не перетирается. - Прод-замер (read-only): **9235/9235** целевых строк резолвятся, 0 нерезолвимых. - Семантика 1:1 с realtime-зеркалом — просто применена к беклогу офлайн. Будущие строки линкуются в реальном времени (e63b21e). - Применение: миграции монтируются в initdb (filename order) на fresh-init (на пустой БД — безвредный no-op) и вручную через psql на проде. Контракт — идемпотентность, не ledger. ## Ревью code-reviewer ✅ APPROVE (join детерминирован, идемпотентность строгая, мислинка нет, конвенция 063/124, GET DIAGNOSTICS корректен, fresh-init без хазарда). Минор: покрывает только листинги с непустыми `house_source/house_ext_id` (целевая когорта несёт catalog-id 100%) — прочие источники с fallback-ключом вне scope (документировано). ## После деплоя В `RAISE NOTICE` ожидается `filled≈9235 | residual_with_extid=0`. Ненулевой WARNING — сигнал к разбору матчинга, не сбой миграции. ## НЕ входит (зона Лёхи / prod-exec, см. #1781) Расширение охвата `cian_city_sweep` (якоря/радиус/анти-бан) + обновление cian-cookies + точечный ре-скрейп Широкой Речки — без этого свежие cian-объявления дома 29 не подтянутся; этот PR только чинит линковку того, что уже есть. Авто-деактивацию протухших novostroyki (`deactivate_stale_cian`) — сиквенсить ПОСЛЕ расширения охвата. Связано: #1774 (PR #1776, estimator Tier A теперь принимает same-building novostroyki).
bot-backend added 1 commit 2026-06-19 11:21:05 +00:00
fix(db): #1781 backfill listings.house_id_fk from house_sources
All checks were successful
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 6s
8adbbef88c
The realtime FK mirror (base.py:607-616) only landed 2026-06-17 (e63b21e).
Listings matched into house_sources before that — notably 9205 cian novostroyki
frozen at 2026-05-31 — never had house_id_fk mirrored back, breaking the
canonical "same-building via house_id_fk" estimator path (93% of active cian
novostroyki had NULL fk citywide).

Add data/sql/130_backfill_listings_house_id_fk.sql: deterministic source-id
backfill via house_sources (ext_source, ext_id → house_id), idempotent
(WHERE house_id_fk IS NULL), no fuzzy/address fallback. Prod (read-only):
9235/9235 target rows resolve deterministically, zero unresolvable. One-time
backlog drain; future rows linked in realtime by the e63b21e mirror.
lekss361 merged commit 7bf39e24df into main 2026-06-19 14:56:10 +00:00
lekss361 deleted branch fix/1781-cian-novostroyki-fk-backfill 2026-06-19 14:56:10 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#1784
No description provided.