fix(cadastre): filter Point/LineString geometry in upsert_parcel/zouit (worker crash root cause) #184
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#184
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/cadastre-parcel-geometry-type-filter"
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
Worker crash root cause from pilot v8 hang at 25/50. Worker logs revealed:
```
psycopg.errors.InvalidParameterValue:
Geometry type (Point) does not match column type (Polygon)
```
Quarter `66:41:0104002` parcel `66:41:0104002:18` — NSPD returned Point geometry for ЗУ без detailed boundary. `cad_parcels.geom` schema is strict POLYGON → INSERT fail → autoretry exhausted → worker died → job hung (heartbeat stale at 15:27:43, never resumed).
Fix
Filter geometry.type at Python level in:
Same pattern as existing `upsert_quarter_geom_from_feature`. Non-Polygon geometry → `geom=NULL`, raw_props preserved (координаты не теряются, доступны для analyze).
Tables with permissive GEOMETRY schema unaffected:
Pilot v8 validation (before crash)
Despite crash, 25 quarters processed validated all 4 prior fixes:
Test plan
Closes part of #168 (Phase 1 geometry crash protection).
Review
CI зелёный (backend 59s + frontend 1m38s) + cross-check (agent):
✅ Schema claims подтверждены
По
data/sql/92_cad_bulk_layers.sql+58_schema_cad_quarters.sql:cad_parcels.geom=GEOMETRY(Polygon, 4326)strict — filter применён ✓cad_zouit.geom=GEOMETRY(MultiPolygon, 4326)strict — filter применён ✓cad_buildings_new/cad_constructions/cad_oncs/cad_enk.geom=GEOMETRY(Geometry, 4326)permissive — filter не нужен ✓cad_quarters_geom.geom=geometry(MultiPolygon, 4326)strict — уже filter'нут вupsert_quarter_geom_from_feature(PR #181) ✓cad_parcels_geom— back-compat VIEW (migration 92 step M), не writeableВсе NSPD-write точки strict-schema таблиц покрыты. Других strict таблиц, которые пишет NSPD bulk harvest, нет.
✅ Pattern consistency
Whitelist
("Polygon", "MultiPolygon")идентиченupsert_quarter_geom_from_feature:1015. Та же defensive idiom:geom = feature.geometry or {},geom.get("type") if isinstance(geom, dict), добавлен INFO log на non-Polygon для ops visibility.✅ raw_props preserved
raw_propsстроится изraw_optsнезависимо отgeom_json(bulk_harvest.py:502, 977) — координаты не теряются, доступны для analyze пайплайна.✅ Edge cases
MultiPoint/GeometryCollection/MultiLineString/empty dict/None — все падают вgeom_json=Noneчерез whitelist. Sane default.✅ Test coverage
3 новых теста:
test_upsert_parcel_skips_geom_for_point_geometry— Point geom → NULL, INSERT proceeds, raw_props сохранёнtest_upsert_parcel_keeps_polygon_geometry— Polygon → kept (happy path)test_upsert_zouit_skips_geom_for_linestring— LineString → NULLAssertions корректны:
db.execute.assert_called_once()+call_params["geom"] is None.✅ Drift отсутствует
Server-side only filter, no TS callers.
Контекст
Это пятый root-cause fix в серии #168 после #175 SSL, #176 floors, #177 parse, #178 cast, #179 broken geom skip, #180 per-cat, #181 auto-heal, #182 metrics, #183 race. После merge + deploy pilot v9 должен наконец-то завершиться 50/50 без crash → ekb_full 2408/2408.
approve merge