refactor(db)!: clean up business SQL access
- make realtime replacement and analysis result writes transactional\n- consolidate SCADA repositories and remove process-global project state\n- validate SCADA batches and use indexed GIS-backed business queries\n\nBREAKING CHANGE: remove the public analysis result writer and the pipeline-health network_name query parameter.
This commit is contained in:
@@ -2,17 +2,41 @@ from fastapi import APIRouter, Depends, HTTPException, Query, Path, Body
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
from psycopg import AsyncConnection
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from app.infra.db.postgresql.scada import ScadaInfoRepository
|
||||
from app.infra.db.timescaledb.repositories.scada import ScadaRepository
|
||||
from .dependencies import get_timescale_connection
|
||||
from .dependencies import get_postgres_connection, get_timescale_connection
|
||||
|
||||
router = APIRouter()
|
||||
SCADA_BATCH_MAX_ITEMS = 10_000
|
||||
|
||||
|
||||
class ScadaReadingBatchItem(BaseModel):
|
||||
time: datetime
|
||||
device_id: str = Field(min_length=1)
|
||||
monitored_value: float | None = None
|
||||
cleaned_value: float | None = None
|
||||
|
||||
@field_validator("device_id")
|
||||
@classmethod
|
||||
def normalize_device_id(cls, value: str) -> str:
|
||||
normalized = value.strip()
|
||||
if not normalized:
|
||||
raise ValueError("device_id must not be blank")
|
||||
return normalized
|
||||
|
||||
|
||||
@router.post("/timeseries/scada-readings/batches", status_code=201, summary="批量插入SCADA监测数据")
|
||||
async def insert_scada_data(
|
||||
data: List[dict] = Body(..., description="SCADA设备监测数据列表"),
|
||||
data: List[ScadaReadingBatchItem] = Body(
|
||||
...,
|
||||
min_length=1,
|
||||
max_length=SCADA_BATCH_MAX_ITEMS,
|
||||
description="SCADA设备监测数据列表",
|
||||
),
|
||||
conn: AsyncConnection = Depends(get_timescale_connection),
|
||||
postgres_conn: AsyncConnection = Depends(get_postgres_connection),
|
||||
):
|
||||
"""
|
||||
批量插入SCADA监测数据
|
||||
@@ -25,7 +49,20 @@ async def insert_scada_data(
|
||||
Returns:
|
||||
插入成功的记录数
|
||||
"""
|
||||
await ScadaRepository.insert_scada_batch(conn, data)
|
||||
rows = [item.model_dump() for item in data]
|
||||
requested_ids = list(dict.fromkeys(item["device_id"] for item in rows))
|
||||
existing_ids = await ScadaInfoRepository.get_existing_device_ids(
|
||||
postgres_conn, requested_ids
|
||||
)
|
||||
missing_ids = [
|
||||
device_id for device_id in requested_ids if device_id not in existing_ids
|
||||
]
|
||||
if missing_ids:
|
||||
raise HTTPException(
|
||||
status_code=422,
|
||||
detail=f"SCADA devices do not exist in BizDB: {', '.join(missing_ids)}",
|
||||
)
|
||||
await ScadaRepository.insert_scada_batch(conn, rows)
|
||||
return {"message": f"Inserted {len(data)} records"}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user