From 8279b0ee1f1d6f19b9b7b9476c3232732e20a85a Mon Sep 17 00:00:00 2001 From: Light1YT Date: Mon, 15 Jun 2026 20:29:00 +0500 Subject: [PATCH] =?UTF-8?q?fix(week-review):=20cross-file=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B8=D0=B2=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=B4-=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D1=8C=D1=8E=20(#1338,=20#1363,=20#1419,=20#1421,?= =?UTF-8?q?=20#1424,=20#1480)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #1338 concepts.py: geometry.generate вынесен в run_in_threadpool (не блокирует event loop) - #1363 house_imv_backfill.py + scrape_pipeline.py: периодический heartbeat в долгих IMV-фазах (reap_zombies не помечает живой sweep zombie) - #1419 site-finder-api.ts: placeholderData keepPreviousData для bbox-запроса (KPI не мигает «0/0» при пане/зуме) - #1421 site-finder-api.ts: area_ha nullable + адаптер не подставляет 0; null-гейт потребителей EntryMap.tsx, ParcelDrawer.tsx - #1424/#1480 EstimateResult.tsx: блок «Параметры объекта» скрыт при восстановлении по shared-ссылке (нет мусора «0 м²/Студия/Этаж 0 из 0») Верификация: tsc --noEmit 0 ошибок; py_compile OK. --- backend/app/api/v1/concepts.py | 5 +- .../components/site-finder/entry/EntryMap.tsx | 4 +- .../site-finder/entry/ParcelDrawer.tsx | 2 +- .../components/trade-in/EstimateResult.tsx | 189 +++++++++--------- frontend/src/lib/site-finder-api.ts | 31 ++- .../app/services/house_imv_backfill.py | 37 ++++ .../backend/app/services/scrape_pipeline.py | 8 + 7 files changed, 177 insertions(+), 99 deletions(-) diff --git a/backend/app/api/v1/concepts.py b/backend/app/api/v1/concepts.py index b33f138c..579212b3 100644 --- a/backend/app/api/v1/concepts.py +++ b/backend/app/api/v1/concepts.py @@ -1,6 +1,7 @@ import logging from fastapi import APIRouter, HTTPException +from fastapi.concurrency import run_in_threadpool from app.schemas.concept import ConceptInput, ConceptOutput from app.services.generative import geometry @@ -23,7 +24,9 @@ async def create_concept(payload: ConceptInput) -> ConceptOutput: 422 rather than empty variants — that is a bad request, not a valid empty result. """ try: - variants = geometry.generate(payload) + # geometry.generate — синхронный CPU-bound (Shapely/STRtree), мостим через + # run_in_threadpool, чтобы НЕ блокировать event loop (тот же приём, что и в chat.py). + variants = await run_in_threadpool(geometry.generate, payload) except ParcelGeometryError as exc: logger.warning("concept generation rejected parcel: %s", exc) raise HTTPException(status_code=422, detail=str(exc)) from exc diff --git a/frontend/src/components/site-finder/entry/EntryMap.tsx b/frontend/src/components/site-finder/entry/EntryMap.tsx index 95830385..6fabb71c 100644 --- a/frontend/src/components/site-finder/entry/EntryMap.tsx +++ b/frontend/src/components/site-finder/entry/EntryMap.tsx @@ -106,7 +106,7 @@ function ParcelMarkers({
{parcel.cad_num}
- {parcel.area_ha.toFixed(2)} га · {statusLabel} + {parcel.area_ha != null ? parcel.area_ha.toFixed(2) : "—"} га · {statusLabel}
Нажмите, чтобы открыть анализ @@ -129,7 +129,7 @@ function ParcelMarkers({
- {parcel.area_ha.toFixed(2)} га · {statusLabel} + {parcel.area_ha != null ? parcel.area_ha.toFixed(2) : "—"} га · {statusLabel}