fix(tradein): hotfix миграции 108 — deploy red (typo + collision-safe репойнт) #1547

Merged
lekss361 merged 1 commit from fix/migration-108-collision-safe into main 2026-06-16 05:48:39 +00:00
Owner

🔴 Деплой main упал на миграции 108 (из #1546) — это hotfix

108_merge_duplicate_houses.sql уронила деплой (_schema_migrations strict exit-1), миграция НЕ применилась (mig108=0, houses всё ещё 13456). Корневая причина: миграция была покрыта только mock-тестами и ни разу не гонялась против реальной БД. Два бага:

Баг 1 — typo: в CTE dup_houses ссылка на c.cluster_key, но алиас таблицы clusteredcl. → ERROR: missing FROM-clause entry for table "c".

Баг 2 — dup-vs-dup коллизия: дедуп-перед-репойнтом сравнивал строку дубля только с каноном. Но в кластере >2 два РАЗНЫХ дубля могут иметь одинаковый unique-ключ → оба репойнтятся на канон → duplicate key. Проявилось на house_suggestions UNIQUE(house_id,ext_item_id) и address_mismatch_audit UNIQUE(house_id,audit_batch).

Фикс

  • c.cluster_keycl.cluster_key.
  • Collision-safe репойнт для таблиц, чей UNIQUE включает house_id: 3c houses_price_dynamics, 3d house_imv_evaluations, 3e house_suggestions, 3i address_mismatch_audit. Паттерн: дедуп по целевому ключу (canonical_id, …) через ROW_NUMBER + id, строка канона выживает (m.canonical_id IS NULL DESC), затем репойнт.
  • 3a/3b (house_sources/house_address_aliases — UNIQUE глобальный, без house_id), 3f/3g/3h (house_reviews/house_reliability_checks/external_valuations — UNIQUE глобальный или только PK) репойнт-безопасны, не менялись.
  • Заголовок: address_mismatch_audit помечен корректным UNIQUE(house_id,audit_batch).

Валидация — dry-run против ПРОД-данных (BEGIN…ROLLBACK), 3 итерации до зелёного

Финальный прогон чистый end-to-end на реальных 4478 дублях:

NOTICE: merge 108 done: houses before=13456, clusters_merged=3878, rows_deleted=4478, after=8978
ROLLBACK

Это сильнее unit-теста — упражняет фактические прод-данные. Ничего не закоммичено (ROLLBACK).

После мержа

Файл 108 заменяется (не 109): миграция ни разу не применилась успешно (mig108=0), на деплое прогонится исправленная версия с нуля. Деплой разблокируется, houses 13456 → 8978.

## 🔴 Деплой main упал на миграции 108 (из #1546) — это hotfix `108_merge_duplicate_houses.sql` уронила деплой (`_schema_migrations` strict exit-1), миграция НЕ применилась (`mig108=0`, houses всё ещё 13456). Корневая причина: миграция была покрыта только mock-тестами и **ни разу не гонялась против реальной БД**. Два бага: **Баг 1 — typo:** в CTE `dup_houses` ссылка на `c.cluster_key`, но алиас таблицы `clustered` — `cl`. → `ERROR: missing FROM-clause entry for table "c"`. **Баг 2 — dup-vs-dup коллизия:** дедуп-перед-репойнтом сравнивал строку дубля только с **каноном**. Но в кластере >2 два РАЗНЫХ дубля могут иметь одинаковый unique-ключ → оба репойнтятся на канон → `duplicate key`. Проявилось на `house_suggestions UNIQUE(house_id,ext_item_id)` и `address_mismatch_audit UNIQUE(house_id,audit_batch)`. ## Фикс - `c.cluster_key` → `cl.cluster_key`. - Collision-safe репойнт для таблиц, чей UNIQUE включает `house_id`: **3c** `houses_price_dynamics`, **3d** `house_imv_evaluations`, **3e** `house_suggestions`, **3i** `address_mismatch_audit`. Паттерн: дедуп по **целевому** ключу `(canonical_id, …)` через `ROW_NUMBER` + `id`, строка канона выживает (`m.canonical_id IS NULL DESC`), затем репойнт. - 3a/3b (`house_sources`/`house_address_aliases` — UNIQUE глобальный, без `house_id`), 3f/3g/3h (`house_reviews`/`house_reliability_checks`/`external_valuations` — UNIQUE глобальный или только PK) репойнт-безопасны, не менялись. - Заголовок: `address_mismatch_audit` помечен корректным `UNIQUE(house_id,audit_batch)`. ## Валидация — dry-run против ПРОД-данных (BEGIN…ROLLBACK), 3 итерации до зелёного Финальный прогон чистый end-to-end на реальных 4478 дублях: ``` NOTICE: merge 108 done: houses before=13456, clusters_merged=3878, rows_deleted=4478, after=8978 ROLLBACK ``` Это сильнее unit-теста — упражняет фактические прод-данные. Ничего не закоммичено (ROLLBACK). ## После мержа Файл 108 заменяется (не 109): миграция ни разу не применилась успешно (`mig108=0`), на деплое прогонится исправленная версия с нуля. Деплой разблокируется, houses 13456 → 8978.
lekss361 added 1 commit 2026-06-16 05:47:16 +00:00
fix(tradein): миграция 108 — typo cl.cluster_key + collision-safe репойнт (dup-vs-dup)
All checks were successful
CI / changes (push) Successful in 9s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Has been skipped
CI / openapi-codegen-check (push) Has been skipped
CI / changes (pull_request) Successful in 8s
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
dca3de10e6
Деплой упал на 108: (1) c.cluster_key → cl.cluster_key (несуществующий алиас);
(2) дедуп-перед-репойнтом сравнивал дубль только с каноном, но два разных дубля
одного кластера с одинаковым unique-ключом коллизили при репойнте на канон.
Переписаны 3c/houses_price_dynamics, 3d/house_imv_evaluations, 3e/house_suggestions,
3i/address_mismatch_audit на collision-safe паттерн (дедуп по целевому ключу,
канон-строка выживает). address_mismatch_audit имеет UNIQUE(house_id,audit_batch) —
заголовок ошибочно помечал «нет UNIQUE».

Валидировано dry-run против прод-данных (4478 реальных дублей):
houses 13456 → 8978, clusters_merged=3878, чисто end-to-end.
lekss361 added the
bug
scope/backend
labels 2026-06-16 05:47:23 +00:00
lekss361 merged commit 7d39aebbd4 into main 2026-06-16 05:48:39 +00:00
lekss361 deleted branch fix/migration-108-collision-safe 2026-06-16 05:48:39 +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#1547
No description provided.