gendesign/backend/app/workers/tasks/utility_infrastructure_sync.py
Light1YT 42ed1f8a93
All checks were successful
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (pull_request) Successful in 54s
CI / openapi-codegen-check (pull_request) Successful in 2m12s
CI / backend-tests (pull_request) Successful in 11m19s
feat(site-finder): OSM engineering-networks loader + endpoint (#1746)
No-B2B open-data путь (Overpass) для инженерных сетей ЕКБ: ЛЭП/подстанции/
опоры, трубопроводы (газ/вода/канализация), ЦТП, вышки связи.

- Миграция 100_osm_utility_infrastructure_ekb.sql: таблица + GIST-индекс,
  UNIQUE(osm_type, osm_id) для идемпотентного UPSERT, geom(Geometry,4326)
  (линии И точки).
- Loader utility_infrastructure_loader.py: Overpass-запросы (rate-limit 1 req/s),
  классификация в infrastructure_kind (power/water/gas/heat/communication/sewage),
  per-element SAVEPOINT UPSERT. Зеркалит noise_loader (геом-хелперы переиспользованы).
- Celery task + weekly beat (понедельник 04:00 МСК, после noise-sync).
- Endpoint GET /api/v1/parcels/{cad}/utility-infrastructure: инж.сети в радиусе
  центроида участка (ST_DWithin) + summary по видам сети. Зеркалит connection-points.
- Тесты: loader (Overpass-парсинг/UPSERT/SAVEPOINT/фильтры) + endpoint (mock DB).
- Codegen: api-types.ts регенерирован (новый endpoint + 3 схемы).
2026-06-27 00:42:02 +05:00

59 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Celery task: еженедельная синхронизация OSM инженерных сетей для site-finder (#1746)."""
import logging
from sqlalchemy import text
from app.workers.celery_app import celery_app
logger = logging.getLogger(__name__)
def _log_breadcrumb(level: str, message: str) -> None:
"""Записать строку в nspd_geo_log (job_id=NULL, stage='utility_sync').
Persistent breadcrumb для диагностики без SSH (как poi_sync / noise_sync).
"""
try:
from app.core.db import SessionLocal
db = SessionLocal()
try:
db.execute(
text(
"INSERT INTO nspd_geo_log (job_id, level, stage, message) "
"VALUES (NULL, :lvl, 'utility_sync', :msg)"
),
{"lvl": level, "msg": message[:500]},
)
db.commit()
finally:
db.close()
except Exception as e:
logger.warning("utility_sync breadcrumb failed: %s", e)
@celery_app.task(
name="tasks.utility_infrastructure_sync.sync_osm_utility_infrastructure_ekb",
queue="celery",
)
def sync_osm_utility_infrastructure_ekb() -> dict:
"""Еженедельная синхронизация OSM инж.сетей из Overpass в osm_utility_infrastructure_ekb.
Запускается через beat (понедельник 04:00 МСК — через 30 мин после noise-sync).
No-B2B open-data источник (Overpass). Persistent breadcrumbs в nspd_geo_log.
"""
_log_breadcrumb("info", "task started")
try:
from app.services.site_finder.utility_infrastructure_loader import (
sync_utility_infrastructure_to_db,
)
result = sync_utility_infrastructure_to_db()
logger.info("utility_sync done: %s", result)
_log_breadcrumb("info", f"done: {result}")
return result
except Exception as e:
logger.exception("utility_sync failed: %s", e)
_log_breadcrumb("error", f"{type(e).__name__}: {e}")
raise