feat(db): bulk cadastre schema — 7 tables + cadastre_jobs (#168 PR1/5) #169
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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#169
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/cadastre-bulk-schema"
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?
Summary
data/sql/92_cad_bulk_layers.sql(647 lines) — 7 new cadastre layer tables + 1 saga-state table for the bulk ingest pipelinecad_parcels_geom→cad_parcels; backs up existingcad_buildings→cad_buildings_old_apr26and replaces with wide schemav_complex_full+v_complex_buildingsviews (depend oncad_buildings)Tables created
cad_parcelscad_buildings(v2)objdoc_idдляtab-group-datalookupcad_constructionsis_egrn)cad_oncscad_enkcad_zouit(reg_numb_border, category_id)cad_quarter_statscnt_*,sum_*,cost_value_total,real_sridcadastre_jobsgeo_jobs)Indexes
geomcolumn for spatial queriescad_num(via PK),quarter_cad_number,objdoc_id,params_purpose,reg_numb_border,category_id,subcategorycadastre_jobs: BTREE onstatus,heartbeat_at,created_at DESCMigration steps (in transaction)
cad_parcels_geom→cad_parcels(ON CONFLICT DO NOTHING)cad_buildings→cad_buildings_old_apr26(guarded)cad_buildings_newfrom backup with type-safe casts (floors TEXT→INT, cultural_heritage TEXT→BOOLEAN, column renames)cad_buildings_new→cad_buildings+ index/constraint renamescad_buildings.complex_id+ viewsv_complex_buildings,v_complex_fullcad_parcels_geom(guarded by existence check)Все DDL обернуто в
BEGIN/COMMIT, idempotent черезIF NOT EXISTS+DO $$ ... $$guards.Test plan
_schema_migrationstracking — no errorsSELECT COUNT(*) FROM cad_parcelsreturns ≥5 (migrated rows)SELECT COUNT(*) FROM cad_buildings_old_apr26returns 10590 (backup intact)SELECT * FROM v_complex_full LIMIT 1works (view restored)\dt cad_*shows 7 new tables + cad_buildings + cad_buildings_old_apr26 + cad_quarters_geom\di gist_*Acceptance per #168
Next PRs in sequence
search_by_quarter,wms_feature_info,list_objects_in_building)bulk_harvest_quarterCelery task + grid_walker + saga state writers/admin/scrape/cadastre(клон/admin/scrape/geo)Closes part 1/5 of #168.
⚠️ Bot review (SHA
c6fb30f, CI ✅) — request changes, не мержуCross-checked агентом — 2 реальных merge-blocker'а в
92_cad_bulk_layers.sql+ lesser concerns. Auto-apply mechanism (PR #151) применит этот файл на первом deploy после merge — fix-forward после merge невозможен без manual psql intervention.🔴 Blocker #1:
DROP TABLE cad_parcels_geomбез gatingStep M делает unconditional
DROP TABLE cad_parcels_geomеслиcad_parcelsсуществует. PR body утверждает "guarded by existence check", но фактическийDO $$проверяет только existence обеих таблиц — не row count и не отсутствие consumer'ов.83_cad_parcels_geom.sqlCOMMENT прямо говорит что таблица используется как fallback в site-finder analyze endpoint. После DROP этот codepath будет вылетать сrelation does not existна prod без rollback window.Fix варианты:
cad_parcelscad_parcels_geomкак VIEW надcad_parcelsдля back-compat:grep -r "cad_parcels_geom" backend/подтвердить ноль references — если consumer'ов нет, добавить explicit comment в migration с timestamp проверки. Доверять docstring'у 83-й миграции нельзя.🔴 Blocker #2: K.3 rename — двойной rename на одно constraint name
Внутри
IF NOT EXISTS (cad_buildings)ветки:Constraint и index делят одно имя (
cad_buildings_new_pkey).ALTER INDEX RENAMEуже автоматически переименовывает PK constraint (PG matches их). SubsequentALTER TABLE RENAME CONSTRAINTупадёт сconstraint cad_buildings_new_pkey does not exist→BEGIN/COMMITобернутая transaction abort'нется на свежем apply.Fix: удалить redundant
RENAME CONSTRAINTline —ALTER INDEX RENAMEдостаточен.🟡 Lesser concerns (не блокеры, но стоит зафиксить в этом PR раз уж касаемся файла)
cadastre_jobs.statusбез CHECK constraint — partial indexWHERE status = 'running'намекает на enum-like usage. Добавь:COMMENT ON TABLEотсутствует для всех 8 таблиц. Existing migrations (63, 83) добавляют — keep convention.updated_atcolumns без BEFORE UPDATE trigger — DEFAULT NOW() не update'ится на UPDATE. Либо добавь trigger (можно reuseset_updated_at()из миграции 90), либо удали column как misleading.cad_parcelsPK =cad_numonly — без source/version. Re-scrape overwrites черезON CONFLICT(которого нет в INSERT). Не блокер для PR1, но flag для PR2 design.Verdict
Не мержу. Жду новый SHA с фиксами Blocker #1 и #2 (и желательно lesser concerns #1-#3 в том же PR — они почти free-cost и предотвратят будущие "минор follow-up" PRs которые мы согласились избегать).
После push нового SHA — re-review на следующем тике cron.
Fixup pushed (
b4bc704)Все 5 пунктов review адресованы:
Blocker #1 —
cad_parcels_geomстал VIEWOld
DROP TABLEзаменён на:DROP TABLE IF EXISTS cad_parcels_geom(guarded bytable_type = 'BASE TABLE')CREATE OR REPLACE VIEW cad_parcels_geom AS SELECT cad_num, geom, raw_props, fetched_at FROM cad_parcelsColumn signature идентична original 4-column table (verified через
get_object_details). Site-finder analyze fallback продолжает работать. PR2/5 переключит callers напрямую наcad_parcels, тогда VIEW можно будет dropp'нуть.Blocker #2 — redundant
RENAME CONSTRAINTremoved (K.3)ALTER TABLE cad_buildings RENAME CONSTRAINT cad_buildings_new_pkey TO cad_buildings_pkeyстрока удалена с комментарием.ALTER INDEX RENAMEуже автоматически переименовывает PK constraint в PG16.Lesser #1 —
cadastre_jobs.statusCHECKInline в CREATE TABLE:
Включены 'cancelled' + 'paused' для admin UI flow.
Lesser #2 —
COMMENT ON TABLE×8 + 1 VIEWStep N добавлен. Все 8 cad_*/cadastre_jobs + cad_parcels_geom VIEW имеют русские descriptions с NSPD category IDs.
Lesser #3 —
set_updated_attriggersStep O. 7
DO $$blocks сpg_triggerguards для idempotent re-apply. Reuses existingset_updated_at()function (verified).cadastre_jobsexcluded — у негоheartbeat_atmechanism.Что не fix'ил (per "не касайся" в spec)
cad_parcelsPK design w/o source/version) — for PR2 designIdempotency сохранена:
CREATE OR REPLACE VIEW,IF NOT EXISTSна table,DO $$guards на triggers — всё survives re-apply.Final review (SHA
b4bc7048, CI ✅) — all 5 items resolvedCross-checked агентом — все 2 blocker'а и 3 lesser concerns зафикшены в этом SHA.
Blockers — fixed
✅
DROP TABLE cad_parcels_geom+CREATE OR REPLACE VIEW(lines 642-672): drop wrapped вDO $$double-guardedEXISTS(cad_parcels) AND EXISTS(cad_parcels_geom AS BASE TABLE). Сразу следуетCREATE OR REPLACE VIEW cad_parcels_geom AS SELECT cad_num, geom, raw_props, fetched_at FROM cad_parcels;— preserves exact 4-column signature site-finder fallback. Inline comment: "Bulk PR2/5 will migrate callers; drop this view then." Чисто.✅ K.3 double-rename removed (lines 506-509): оставлен только
ALTER INDEX IF EXISTS ... RENAME TO cad_buildings_pkey. RedundantALTER TABLE ... RENAME CONSTRAINTудалён. Inline comment документирует PG16 behavior.Lesser concerns — fixed (per "no minor follow-up" policy)
✅
cadastre_jobs.statusCHECK (lines 299-302):CHECK (status IN ('queued','running','done','failed','zombie','cancelled','paused')). Default 'queued' в allowed set.✅ COMMENT ON TABLE × 8 (Section N, lines 675-709): cad_parcels, cad_buildings, cad_constructions, cad_oncs, cad_enk, cad_zouit, cad_quarter_stats, cadastre_jobs. Russian descriptions с categoryIds.
✅ BEFORE UPDATE triggers × 7 (Section O, lines 712-786):
set_updated_at()для каждой таблицы сupdated_at. Idempotency черезpg_triggerlookup (PG16 не имеетCREATE OR REPLACE TRIGGER).cadastre_jobsправильно исключен — используетheartbeat_atвместоupdated_at.Verdict
mergeStateStatus=CLEAN, mergeable=MERGEABLE, backend + frontend CI SUCCESS. Все исправления defensible, idempotent, well-commented.
approve merge