fix(ptica): ключ gisogd_permits — id документа на портале, а не (группа, номер) (#2986) #2987
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2987
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2986-permits-key"
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?
Закрывает #2986 (там же полный разбор с замерами).
Коротко
UNIQUE (doc_group, doc_num)вводился ради склейки одного документа из двух схем портала. Схемы пересекаются на 2 документа. Ключ при этом схлопывает 2243 разных документа, потому чтоdocNumу ГИСОГД не уникален: разрешение и изменения к нему носят один номер.На проде 9182 строки против 12 065 документов на портале — нет 23.9 % реестра.
Что именно теряется
docNum = 66-06-06-2026, группа DocRS — портал отдаёт два разных документа:На проде осталось одно — изменение (у него
date_regпозже, UPSERT предпочитает поздний). Самого разрешения нет.Не единичный случай: 598 из 4320 строк РНС (13.8 %) названы «Изменения…» — в этих случаях изменение вытеснило исходное разрешение, и §6 показывает его вместо разрешения без всякого признака подмены.
Правка
UNIQUE (doc_group, doc_num)UNIQUE (source_key)GROUP_CODE = {DocRS, DocRV}+ DocIZ → 'IZ'(548 документов не грузились вовсе)CHECK doc_group IN ('RS','RV')+ 'IZ'source_key— идентификатор документа на портале. Он разделяет разрешение и изменения (разные key) и по-прежнему склеивает настоящие межсхемные дубли: у тех key ОБЩИЙ (ровно 7 записей по всем трём группам).Дедуп перед сменой ключа не нужен — проверено на проде:
source_keyуже уникален, 9182 различных на 9182 строки, NOT NULL.(doc_group, doc_num)остаётся обычным индексом: как фильтр «все документы по номеру» он полезен, просто не уникален.§6 сужена явно, а не молча
Агрегат
permits_nearbyобещаетtotal_count = rs_count + rv_count. Строки'IZ'попадали бы вtotalи ни в один из счётчиков. Поэтому запрос сужен доdoc_group IN ('RS','RV')явно, с комментарием: показывать ли изменения отдельной строкой — вопрос продуктовый, и до его решения инвариант не должен держаться на том, что таких строк «пока нет».То есть пользователь этого PR не заметит по составу групп, но увидит больше разрешений: вернутся 2243 документа, вытесненные ключом.
Как проверено
origin/mainGROUP_CODE={'DocRS': 'RS', 'DocRV': 'RV'}и в тексте UPSERT стоитON CONFLICT (doc_group, doc_num)— конкретные неверные значения, не отсутствующие символы.total == rs + rv) — красные наorigin/main.key) по-прежнему склеивается в одну строку — то, ради чего старый ключ и вводился.'IZ'принимается, мусорная группа отвергается с именем констрейнта.permits_nearby).Контроль метода разведки: заведомо рабочая комбинация
razdel13/DocRSтем же curl отдаёт 200 и валидный JSON — значит 400-е на других разделах означают отсутствие разделов, а не сломанную пробу.После деплоя
Миграция только меняет ключ; недостающие документы вернутся следующим прогоном загрузчика. Отчитаюсь числами: строк в
gisogd_permits≈ 12 058, из нихdoc_group='IZ'≈ 393, и по номеру 66-06-06-2026 должны появиться ДВЕ строки RS вместо одной.`UNIQUE (doc_group, doc_num)` вводился, чтобы склеивать ОДИН документ, пришедший из двух схем портала. Замер 20.08.2026 показал, что задача, ради которой ключ введён, почти отсутствует, а побочный эффект огромен: docNum у ГИСОГД НЕ уникален — разрешение и изменения к нему носят один номер. группа документов различных key различных docNum схлопывается DocRS 6098 6096 4305 1793 DocRV 5419 5415 4969 450 DocIZ 548 547 393 155 общих docNum между схемами (DocRS): 2 ← ради этого ключ и вводился общих key между схемами (DocRS): 2 ← те же два На проде 9182 строки против 12 065 документов на портале — нет 23.9 % реестра. Пример 66-06-06-2026: портал отдаёт два документа (key …719586 — само разрешение, key …752293 — изменения к нему), а UPSERT с предпочтением позднего date_reg оставлял только изменение. Так вытеснено 598 из 4320 строк РНС (13.8 %) — в §6 на месте разрешения показывается изменение к нему, без признака подмены. Ключ стал `UNIQUE (source_key)`: разделяет разрешение и изменения (разные key) и по-прежнему склеивает настоящие межсхемные дубли (у них key ОБЩИЙ — ровно 7 записей по всем группам). Дедуп перед сменой не нужен: source_key на проде уже уникален (9182 из 9182, NOT NULL). Заодно группа DocIZ добавлена в GROUP_CODE — её не было вовсе, 548 документов не грузились. CHECK расширен значением 'IZ'. §6 сужена до РНС/РВЭ ЯВНО: агрегат обещает total_count = rs_count + rv_count, а строки 'IZ' попадали бы в total и ни в один счётчик. Показывать ли изменения отдельной строкой — вопрос продуктовый (#2986); до его решения сужение стоит в запросе, а не держится на том, что таких строк «пока нет». Проверки: - два гейта на лоадер (GROUP_CODE и цель ON CONFLICT) — БЕЗ базы, двусторонние: на origin/main дают конкретные неверные значения ({'DocRS','DocRV'} и старый ON CONFLICT в тексте запроса); - гейт на §6 и контроль инварианта total = rs + rv на данных — красные на origin/main; - герметичная репетиция миграции на временной копии: со старым ключом разрешение и изменение схлопываются в одну строку (и остаётся именно изменение — как на проде), после миграции живут раздельно; межсхемный дубль по-прежнему склеивается; CHECK принимает 'IZ' и отвергает мусор. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>4587a73f88to9e04086dafПроверено на проде
Деплой
0185889fзелёный. Миграция 192 применилась — констрейнты на проде:Прежнего
UNIQUE (doc_group, doc_num)больше нет,'IZ'теперь допустим.Чего проверка ещё НЕ показывает
Строки на месте:
RV 4862 / RS 4320 / IZ 0— ровно как до миграции. Это ожидаемо: миграция меняет только ключ, а недостающие 2883 документа вернёт загрузчик. Отсутствие изменений в данных сейчас ничего не доказывает — их и не должно было быть.gisogd-permits-weeklyходит по расписанию30 6 * * tue(вторник 06:30 МСК), последний успех — 11.08. Ближайший прогон — вторник 25.08.2026. Вручную не запускаю: это ~2900 новых карточек к стороннему госпорталу, у загрузчика своя вежливая пауза и circuit breaker, и правильный момент для этого — его собственное расписание.Критерий с датой — 25.08.2026
После вторничного прогона на проде должно быть:
Последняя строка — самая говорящая: рядом с изменением должно появиться само разрешение на строительство, которого в данных не было.
Если 26.08 числа не сойдутся — значит дело не в ключе, и разбираться надо дальше, а не считать пункт закрытым.