fix(tradein/yandex): «непригодных» 3535 не было — адресуем их по offerId #2838
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#2838
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/yandex-unenrichable-frozen"
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?
Что было
yandex_detail_backfillшесть прогонов подряд писалunenrichable_pending= ровно 3535, ни на единицу, при том что очередь обогащалась по ~500 за прогон.Диагноз
Из трёх версий (честная константа / застывшая выборка / мёртвая ветка) верна оказалась четвёртая: арифметика честная, а ярлык — нет.
SELECT count(*)— воспроизведён на проде, даёт те же 3535. Ни кэша, ни матвьюхи.source_urlне переписывается). Вопрос был не «почему не растёт», а «правда ли непригодны».source_idлежит числовой yandexofferId(у 3523 продублирован вyandex_offer_id). Живая проба прод-трактом (тот же прокси, curl_cffi chrome120, тот жеYandexDetailScraper.parse, БЕЗ записи): 6 из 6 → HTTP 200 + parse OK, включая строки, чей сохранённыйsource_url— рекламный редиректna100.pro/go.php, и строки, не переобойденные с 17.06.Корень
source_urlпишется только при вставке — его нет ни вON CONFLICT DO UPDATE, ни в reconcile-UPDATE уsave_listings. Поэтому #2235 (канонизация URL в продюсере) вылечил только новые строки, а миграция 164 — только те легаси, чей URL делили несколько строк (она искала дубли URL, а не непарсимость). Строки с уникальной ссылкой на карточку застройщика (macroserver.ru/id/…,strana.com/…/flats/…) не попали ни туда, ни туда и носят адрес, замороженный в момент вставки, хотя свип переобходит ~511 из них в сутки.Что в PR
source_id(та же формула, что у продюсера и у миграции 164), а не выбрасывает их.url_from_offer_id(адрес чиним; должен убывать от прогона к прогону) иunenrichable_pending(адресовать нечем — ни offer-URL, ни числовогоsource_id; на проде 0). Одно число на две разные судьбы читалось как «тут делать нечего» и держало 3535 квартир вне обогащения неделю. Наблюдаемость не убрана, а разделена.Проверка
SQL прогнан на проде read-only, ровно в том виде, в каком его строит задача:
url_from_offer_id=3535,unenrichable_pending=0Тесты — с красным прогоном (оба сторожа падают, если ломать то, что они стерегут):
origin/main→test_pending_counter_split_by_reasonFAILED;test_recovered_url_equals_producer_canonical_formFAILED (сверяется с_canonical_source_urlпродюсера, а не с ожиданием из той же настройки).15 passed, ruff чист.Требует отдельной работы (НЕ здесь)
Миграция — починка самой колонки
source_urlодноразовым UPDATE: тот же 164, но без условия на дубли (source='yandex' AND source_url !~ '/offer/[0-9]+' AND source_id ~ '^[0-9]+$'). Проверено: коллизий 0; долговечность доказана самой 164 — сегодня активных yandex-строк с общимsource_url0 групп, т.е. переписанное не откатывается. От этого зависит иyandex_address_backfill: у него 1618 из 5217 кандидатов ходят на сайты застройщиков вместо Яндекса (прогон 3586: checked 200, saved 1, errors 21).Отдельно на подумать:
source_urlвнеON CONFLICT DO UPDATE— сейчас утечки нет (продюсер канонический), но любая будущая порча адреса так же не самозалечится.Критерий приёмки выполнен — замером, а не рассуждением
Критерий записан 12.08 до факта: «в счётчиках следующего прогона
url_from_offer_idдолжен быть меньше 3535; если снова ровно 3535 — правка не доехала».url_from_offer_idunenrichable_pendingОба счётчика в нуле, и оба нуля правильные: у первого — «адресовать по идентификатору больше нечего», у второго — «нечем адресовать не осталось».
Состояние очереди на тот же момент:
То есть механизм не просто перестал жаловаться — он начал работать: +540 обогащённых за сутки при полностью вычищенных адресах.
Ловушка, которую этот критерий и снимал
Если бы я посмотрел на счётчик сразу после мержа, увидел бы
3535и заключил «правка не доехала». На деле те прогоны стартовали за семь часов до деплоя (08:08 против 15:35). Сравнение по номеру прогона и времени старта, а не по факту мержа, — единственное, что отделило верный вывод от неверного.Ровно поэтому критерий и был записан заранее, с указанием, какое число означает провал.