fix(tradein/scraper): строка с пустым сегментом самочинится при пересборе #2911

Merged
lekss361 merged 1 commit from fix/tradein-upsert-segment-selfheal into main 2026-08-15 19:37:17 +00:00

1 commit

Author SHA1 Message Date
bot-backend
aee0d36e7a fix(tradein/scraper): listing_segment самочинится при upsert вместо вечного NULL
All checks were successful
CI Trade-In / changes (pull_request) Successful in 12s
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
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 Trade-In / backend-tests (pull_request) Successful in 5m1s
Раньше listing_segment писался ТОЛЬКО при INSERT в save_listings — строка,
единожды родившаяся с NULL-сегментом (классификатор не сработал на первом
скрейпе), никогда не получала сегмент на повторных сборах, даже когда он
становился определим. Симптом лечила отдельная джоба деактивации
(deactivate_stale_{cian,yandex}_null_segment, миграция 266, PR #2908) — чистит
мусор, но не саму запись.

Добавлен listing_segment = COALESCE(EXCLUDED.listing_segment,
listings.listing_segment) в ON CONFLICT DO UPDATE, и тот же идиом в
reconcile-UPDATE (dedup_hash-drift fallback path) — иначе self-heal был бы
неполным для строк, прошедших через этот путь. COALESCE, а не голый EXCLUDED,
чтобы повторный скрейп без определённого сегмента не затирал уже известное
значение пустым (тот же паттерн, что уже применён для city/kitchen/ceiling).

Тесты: tests/test_listing_segment_upsert_selfheal.py — INSERT-путь,
ON CONFLICT COALESCE (обе стороны), reconcile-UPDATE COALESCE.
2026-08-15 22:28:05 +03:00