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:
@@ -14,7 +14,6 @@ from app.infra.db.postgresql.scada import ScadaInfoRepository
|
||||
from app.infra.db.timescaledb.repositories.realtime import RealtimeRepository
|
||||
from app.infra.db.timescaledb.repositories.analysis import AnalysisResultsRepository
|
||||
from app.infra.db.timescaledb.repositories.scada import ScadaRepository
|
||||
from app.native.wndb.model.pipes import get_pipes_by_property
|
||||
|
||||
|
||||
class CompositeQueries:
|
||||
@@ -454,20 +453,25 @@ class CompositeQueries:
|
||||
if not cleaned_rows:
|
||||
raise ValueError("SCADA 数据清洗未产生任何数据库更新")
|
||||
|
||||
updated_rows = await ScadaRepository.update_scada_field_batch(
|
||||
timescale_conn,
|
||||
cleaned_rows,
|
||||
"cleaned_value",
|
||||
)
|
||||
if updated_rows == 0:
|
||||
raise ValueError("SCADA 清洗结果未匹配任何已有监测数据")
|
||||
expected_rows = len({(row[0], row[1]) for row in cleaned_rows})
|
||||
async with timescale_conn.transaction():
|
||||
updated_rows = await ScadaRepository.update_scada_field_batch(
|
||||
timescale_conn,
|
||||
cleaned_rows,
|
||||
"cleaned_value",
|
||||
)
|
||||
if updated_rows != expected_rows:
|
||||
raise ValueError(
|
||||
"SCADA 清洗目标在写入期间发生变化,"
|
||||
f"预期更新 {expected_rows} 行,实际更新 {updated_rows} 行"
|
||||
)
|
||||
|
||||
return "success"
|
||||
|
||||
@staticmethod
|
||||
async def predict_pipeline_health(
|
||||
timescale_conn: AsyncConnection,
|
||||
network_name: str,
|
||||
postgres_conn: AsyncConnection,
|
||||
query_time: datetime,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
@@ -478,7 +482,6 @@ class CompositeQueries:
|
||||
|
||||
Args:
|
||||
timescale_conn: TimescaleDB 异步连接
|
||||
db_name: 管网数据库名称
|
||||
query_time: 查询时间
|
||||
property_conditions: 可选的管道筛选条件,如 {"diameter": 300}
|
||||
|
||||
@@ -505,12 +508,21 @@ class CompositeQueries:
|
||||
# 3. 只查询有流速数据的管道的基本信息
|
||||
valid_link_ids = list(velocity_data.keys())
|
||||
|
||||
# 批量查询这些管道的详细信息
|
||||
fields = ["id", "diameter", "node1", "node2"]
|
||||
all_links = get_pipes_by_property(network_name, fields=fields)
|
||||
# GIS 物化视图是低频更新管网的查询面;只读取本次有结果的管道。
|
||||
async with postgres_conn.cursor() as cur:
|
||||
await cur.execute(
|
||||
"""
|
||||
SELECT id, diameter, start_node_id AS node1,
|
||||
end_node_id AS node2
|
||||
FROM gis.pipes
|
||||
WHERE id = ANY(%s)
|
||||
""",
|
||||
(valid_link_ids,),
|
||||
)
|
||||
all_links = await cur.fetchall()
|
||||
|
||||
# 转换为字典以快速查找
|
||||
links_dict = {link["id"]: link for link in all_links}
|
||||
links_dict = {str(link["id"]): link for link in all_links}
|
||||
|
||||
# 获取所有需要查询的节点ID
|
||||
node_ids = set()
|
||||
|
||||
Reference in New Issue
Block a user