[P2] yandex: 204 активных URL-дубля — дедуп + уникальность source_url #2235

Closed
opened 2026-07-02 21:32:09 +00:00 by lekss361 · 1 comment
Owner

Из аудита 2026-07-02 (Фаза 4, verified на проде 2026-07-03: 204 source_url с >1 активной строкой у source='yandex').

Находка: дубли одного объявления (тот же source_url) среди is_active yandex-строк — двойной счёт в аналогах (кросс-source дедуп #2173 ловит только физключ с price_bucket; одинаковый URL с чуть разъехавшимися полями может просочиться) + мусор в UI-списках.

Acceptance:

  • Одноразовая идемпотентная миграция: схлопнуть дубли (оставить свежайший scraped_at, остальные is_active=false).
  • Инвариант: partial unique index на (source, source_url) WHERE is_active AND source_url IS NOT NULL — ИЛИ (если ломает upsert-пути) уникальность в ETL/matching с тестом.
  • Разобраться, каким путём дубли создаются (yandex upsert по source_id? url-вариации с параметрами?) — починить корень, не только симптом.
  • Проверка на проде: 0 активных url-дублей после деплоя.

Scope: tradein-mvp/backend/data/sql/, scrapers/matching yandex-путь.

Из аудита 2026-07-02 (Фаза 4, verified на проде 2026-07-03: 204 source_url с >1 активной строкой у source='yandex'). **Находка:** дубли одного объявления (тот же source_url) среди is_active yandex-строк — двойной счёт в аналогах (кросс-source дедуп #2173 ловит только физключ с price_bucket; одинаковый URL с чуть разъехавшимися полями может просочиться) + мусор в UI-списках. **Acceptance:** - [ ] Одноразовая идемпотентная миграция: схлопнуть дубли (оставить свежайший scraped_at, остальные is_active=false). - [ ] Инвариант: partial unique index на (source, source_url) WHERE is_active AND source_url IS NOT NULL — ИЛИ (если ломает upsert-пути) уникальность в ETL/matching с тестом. - [ ] Разобраться, каким путём дубли создаются (yandex upsert по source_id? url-вариации с параметрами?) — починить корень, не только симптом. - [ ] Проверка на проде: 0 активных url-дублей после деплоя. Scope: `tradein-mvp/backend/data/sql/`, scrapers/matching yandex-путь.
lekss361 added the
data
priority/p2
scope/backend
tradein
labels 2026-07-02 21:33:30 +00:00
Author
Owner

Задеплоено и верифицировано на проде (2026-07-03 07:2x UTC, PR #2271).

  • Миграция 164 применилась деплоем: активные yandex URL-дубль-группы 204 → 0.
  • Инвентарь цел: yandex_active = 9064 (ничего не деактивировано — миграция недеструктивная по дизайну).
  • 5529 активных yandex-строк несут канонический realty.yandex.ru/offer/<id> URL; новые INSERT'ы каноникализируются скрейпером (+ зеркало scraper-kit).
  • Health 200, деплой success.

Напоминание root cause для истории: «дубли» были реальными разными квартирами новостроек, делившими URL лендинга застройщика — дедуп-по-URL с деактивацией уничтожил бы ~1049 живых объявлений. Исправлена колонка, не строки.

**Задеплоено и верифицировано на проде (2026-07-03 07:2x UTC, PR #2271).** - Миграция 164 применилась деплоем: активные yandex URL-дубль-группы **204 → 0**. - Инвентарь цел: yandex_active = 9064 (ничего не деактивировано — миграция недеструктивная по дизайну). - 5529 активных yandex-строк несут канонический `realty.yandex.ru/offer/<id>` URL; новые INSERT'ы каноникализируются скрейпером (+ зеркало scraper-kit). - Health 200, деплой success. Напоминание root cause для истории: «дубли» были реальными разными квартирами новостроек, делившими URL лендинга застройщика — дедуп-по-URL с деактивацией уничтожил бы ~1049 живых объявлений. Исправлена колонка, не строки.
Sign in to join this conversation.
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#2235
No description provided.