69 lines
3.1 KiB
Python
69 lines
3.1 KiB
Python
"""Celery task: инкрементальная синхронизация реестра РНС/РВЭ ГИСОГД-СО (#2367).
|
||
|
||
Источник: открытый JSON-API gisogd66.midural.ru (раздел 13), БЕЗ авторизации и БЕЗ
|
||
гео-блока — задача может выполняться и локально, и на проде. Держим weekly (обновляется
|
||
ежедневно, но лоадер инкрементален и дёшев при отсутствии изменений). Persistent
|
||
breadcrumbs в nspd_geo_log (как connection_capacity_sync). Import-light: тяжёлый
|
||
загрузчик импортируется лениво внутри таска.
|
||
"""
|
||
|
||
import logging
|
||
|
||
from sqlalchemy import text
|
||
|
||
from app.workers.celery_app import celery_app
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _log_breadcrumb(stage: str, level: str, message: str) -> None:
|
||
"""Записать строку в nspd_geo_log (job_id=NULL) — диагностика без SSH."""
|
||
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, :stage, :msg)"
|
||
),
|
||
{"lvl": level, "stage": stage, "msg": message[:500]},
|
||
)
|
||
db.commit()
|
||
finally:
|
||
db.close()
|
||
except Exception as e:
|
||
logger.warning("gisogd_permits breadcrumb failed: %s", e)
|
||
|
||
|
||
@celery_app.task(
|
||
name="tasks.gisogd_permits_sync.sync_gisogd_permits",
|
||
queue="celery",
|
||
# Холодный прогон ~6k карточек (2 схемы × RS+RV) при politeness-sleep укладывается
|
||
# в ~25 мин; щедрый лимит по конвенции full_report/forecast, чтобы beat-ран не убили
|
||
# mid-upsert. Инкрементальные прогоны — минуты.
|
||
time_limit=3600,
|
||
soft_time_limit=3300,
|
||
)
|
||
def sync_gisogd_permits() -> dict:
|
||
"""Инкрементально загрузить РНС/РВЭ ГИСОГД-СО (обе схемы, обе группы) → gisogd_permits.
|
||
|
||
Список группы → сверка с БД по (source_key, date_reg) → карточки только для
|
||
новых/изменившихся → UPSERT по (doc_group, doc_num) с предпочтением позднего date_reg.
|
||
|
||
Returns: счётчики {listed, fetched_details, inserted, updated, skipped_unchanged,
|
||
no_cad, no_geom}.
|
||
"""
|
||
_log_breadcrumb("gisogd_permits_sync", "info", "task started")
|
||
try:
|
||
from app.services.scrapers.gisogd66 import load_gisogd_permits
|
||
|
||
result = load_gisogd_permits()
|
||
logger.info("sync_gisogd_permits done: %s", result)
|
||
_log_breadcrumb("gisogd_permits_sync", "info", f"done: {result}")
|
||
return result
|
||
except Exception as e:
|
||
logger.exception("sync_gisogd_permits failed: %s", e)
|
||
_log_breadcrumb("gisogd_permits_sync", "error", f"{type(e).__name__}: {e}")
|
||
raise
|