fix(site-finder): narrow except clauses, fix quarter fallback WKT, add LIMIT to zouit query

Addresses review-bot blockers on PR #190 (4 reviews flagged same issues):

1. Narrow except in quarter_dump_lookup.py:
   - line 579/651: except Exception -> (OperationalError, ProgrammingError) для outer DB queries
   - line 598/668: except Exception -> (ValueError, json.JSONDecodeError) для json.loads fallback

2. _get_parcel_wkt fallback (line 506-521): cad_quarters_geom хранит 3-segment quarter keys,
   а cad_num передавался 4-segment -> fallback всегда возвращал NULL. Теперь derive_quarter_cad(cad_num).

3. _get_zouit_engineering_overlaps: добавлен LIMIT 100 для unbounded jsonb_array_elements fan-out
   (engineering_structures query уже имел LIMIT 50).
This commit is contained in:
lekss361 2026-05-16 08:55:53 +03:00
parent fad815c728
commit 0cf0ab3358

View file

@ -19,6 +19,7 @@ from datetime import UTC, datetime, timedelta
from typing import Any from typing import Any
from sqlalchemy import text from sqlalchemy import text
from sqlalchemy.exc import OperationalError, ProgrammingError
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -505,7 +506,9 @@ def _get_parcel_wkt(db: Session, cad_num: str) -> str | None:
if row is not None and row[0] is not None: if row is not None and row[0] is not None:
return str(row[0]) return str(row[0])
# Fallback: кварталы (более крупный объект — менее точно, но лучше чем ничего) # Fallback: кварталы (более крупный объект — менее точно, но лучше чем ничего).
# cad_quarters_geom хранит 3-сегментные ключи (66:41:0204016), не 4-сегментные.
quarter_key = derive_quarter_cad(cad_num)
row = db.execute( row = db.execute(
text( text(
""" """
@ -515,7 +518,7 @@ def _get_parcel_wkt(db: Session, cad_num: str) -> str | None:
LIMIT 1 LIMIT 1
""" """
), ),
{"c": cad_num}, {"c": quarter_key},
).first() ).first()
if row is not None and row[0] is not None: if row is not None and row[0] is not None:
return str(row[0]) return str(row[0])
@ -573,7 +576,7 @@ def _get_engineering_structures_by_boundary(
), ),
{"q": quarter, "wkt": parcel_wkt, "radius_m": radius_m}, {"q": quarter, "wkt": parcel_wkt, "radius_m": radius_m},
).fetchall() ).fetchall()
except Exception as e: except (OperationalError, ProgrammingError) as e:
logger.warning( logger.warning(
"engineering_structures query failed for quarter=%s: %s", "engineering_structures query failed for quarter=%s: %s",
quarter, quarter,
@ -592,7 +595,7 @@ def _get_engineering_structures_by_boundary(
if geom_raw: if geom_raw:
try: try:
geom_dict = json.loads(geom_raw) geom_dict = json.loads(geom_raw)
except Exception: except (ValueError, json.JSONDecodeError):
geom_dict = {} geom_dict = {}
result.append( result.append(
@ -641,11 +644,12 @@ def _get_zouit_engineering_overlaps(
), ),
ST_GeomFromText(:wkt, 4326) ST_GeomFromText(:wkt, 4326)
) )
LIMIT 100
""" """
), ),
{"q": quarter, "wkt": parcel_wkt}, {"q": quarter, "wkt": parcel_wkt},
).fetchall() ).fetchall()
except Exception as e: except (OperationalError, ProgrammingError) as e:
logger.warning( logger.warning(
"zouit_engineering query failed for quarter=%s: %s", "zouit_engineering query failed for quarter=%s: %s",
quarter, quarter,
@ -662,7 +666,7 @@ def _get_zouit_engineering_overlaps(
if geom_raw: if geom_raw:
try: try:
geom_dict = json.loads(geom_raw) geom_dict = json.loads(geom_raw)
except Exception: except (ValueError, json.JSONDecodeError):
geom_dict = {} geom_dict = {}
subcategory_raw = props.get("subcategory") subcategory_raw = props.get("subcategory")