From 85c43ff68b959b98fdcb4660f576226a40a47771 Mon Sep 17 00:00:00 2001 From: Light1YT Date: Wed, 3 Jun 2026 19:59:59 +0500 Subject: [PATCH] fix(analyze): cad_exists_in_db must require non-NULL geometry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complements the NULL-geom 500 fix. cad_exists_in_db (docstring: "is there GEOMETRY") checked only row existence, not geom IS NOT NULL — so for the ~964 meta-but-NULL-geom parcels it returned True. Consequence after the 500 fix: such a parcel fell into the analyze fallback, find_or_enqueue_fetch step 2 saw cad_exists_in_db=True → returned ("ready", None) → NO NSPD fetch enqueued → analyze looped to a 202 with job_id=null and the parcel was stuck "fetching" forever (never pulled real geometry, never resolved). Fix: add `AND geom IS NOT NULL` to all three EXISTS branches (aligns the function with its docstring). Now a NULL-geom parcel → cad_exists_in_db=False → a real NSPD fetch is enqueued (202 + real job_id) → geometry populates → re-poll → analyze succeeds (or 404 not_in_nspd if NSPD lacks it). No more stuck-202. Valid-geom parcels unaffected. All 3 callers want geometry-presence semantics. 37 analyze/fetch/by-bbox tests green. Refs #944. --- .../app/services/site_finder/cadastre_fetch.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/backend/app/services/site_finder/cadastre_fetch.py b/backend/app/services/site_finder/cadastre_fetch.py index c995fe70..9c81c0a4 100644 --- a/backend/app/services/site_finder/cadastre_fetch.py +++ b/backend/app/services/site_finder/cadastre_fetch.py @@ -65,19 +65,28 @@ def validate_cad_format(cad_num: str) -> bool: def cad_exists_in_db(db: Session, cad_num: str) -> bool: - """Проверка: есть ли geometry для cad_num в любой из 3 таблиц. + """Проверка: есть ли НЕПУСТАЯ geometry для cad_num в любой из 3 таблиц. Использует EXISTS short-circuit — самая дешёвая проверка. + + NB: `geom IS NOT NULL` обязателен — есть ~964 строк в cad_parcels_geom с meta, + но NULL-геометрией. Без фильтра функция врала бы «geometry есть» → analyze + fallback решал бы "ready"/не ставил NSPD-fetch → участок навсегда застревал в + 202 (никогда не подтянул бы реальную геометрию). С фильтром null-geom участок + корректно идёт в fetch → НСПД отдаёт геометрию → analyze работает (или 404). """ row = db.execute( text( """ SELECT 1 WHERE EXISTS ( - SELECT 1 FROM cad_quarters_geom g WHERE g.cad_number = :c + SELECT 1 FROM cad_quarters_geom g + WHERE g.cad_number = :c AND g.geom IS NOT NULL UNION ALL - SELECT 1 FROM cad_buildings b WHERE b.cad_num = :c + SELECT 1 FROM cad_buildings b + WHERE b.cad_num = :c AND b.geom IS NOT NULL UNION ALL - SELECT 1 FROM cad_parcels_geom p WHERE p.cad_num = :c + SELECT 1 FROM cad_parcels_geom p + WHERE p.cad_num = :c AND p.geom IS NOT NULL ) LIMIT 1 """ ),