refactor: simplify task and history services

Remove retired query paths and repository compatibility branches, and share task test fixtures.
Cancel pending questions and resolve their notifications when recovering expired runs.
This commit is contained in:
2026-11-09 17:55:00 +08:00
parent 5197a93163
commit 6a4478bfe4
10 changed files with 464 additions and 816 deletions
+18 -103
View File
@@ -1,10 +1,10 @@
import asyncio
from datetime import datetime, timezone
from unittest.mock import AsyncMock
from uuid import uuid4
from app.api.v1.endpoints import scada as scada_endpoint
from app.services import timeseries_analysis as composite_queries
from app.services import timeseries_history as history
from app.domain.schemas.timeseries_history import ElementHistoryQuery
PROJECT_SCADA = {
@@ -26,107 +26,22 @@ START_TIME = datetime(2026, 6, 1, tzinfo=timezone.utc)
END_TIME = datetime(2026, 6, 2, tzinfo=timezone.utc)
def _patch_project_scadas(monkeypatch):
monkeypatch.setattr(
composite_queries.ScadaInfoRepository,
"get_scadas",
AsyncMock(return_value=[PROJECT_SCADA.copy()]),
)
def test_realtime_scada_simulation_uses_current_project_metadata(monkeypatch):
_patch_project_scadas(monkeypatch)
query_mock = AsyncMock(
return_value={"J1": [{"time": START_TIME, "value": 26.5}]}
)
monkeypatch.setattr(
composite_queries.RealtimeRepository,
"get_node_fields_by_ids_time_range",
query_mock,
)
monkeypatch.setattr(
composite_queries.RealtimeRepository,
"get_link_fields_by_ids_time_range",
AsyncMock(return_value={}),
)
result = asyncio.run(
composite_queries.TimeseriesAnalysisService.get_scada_associated_realtime_simulation_data(
object(),
object(),
[PROJECT_SCADA["device_id"]],
START_TIME,
END_TIME,
)
)
assert result[PROJECT_SCADA["device_id"]][0]["scada_id"] == PROJECT_SCADA["device_id"]
assert query_mock.await_count == 1
assert query_mock.await_args.args[1:] == (
START_TIME,
END_TIME,
["J1"],
"pressure",
)
def test_analysis_scada_simulation_uses_current_project_metadata(monkeypatch):
_patch_project_scadas(monkeypatch)
async def query_series(_conn, _run_id, element_type, element_ids, *_args):
if element_type == "node":
return {"J1": [{"time": START_TIME, "value": 26.5}]}
return {}
query_mock = AsyncMock(side_effect=query_series)
monkeypatch.setattr(
composite_queries.AnalysisResultsRepository,
"get_series_by_ids",
query_mock,
)
result = asyncio.run(
composite_queries.TimeseriesAnalysisService.get_scada_associated_analysis_simulation_data(
object(),
object(),
[PROJECT_SCADA["device_id"]],
START_TIME,
END_TIME,
uuid4(),
)
)
assert result[PROJECT_SCADA["device_id"]][0]["scada_id"] == PROJECT_SCADA["device_id"]
assert query_mock.await_count == 2
node_call = next(
call for call in query_mock.await_args_list if call.args[2] == "node"
)
assert node_call.args[3:] == (["J1"], START_TIME, END_TIME, "pressure")
def test_element_scada_query_uses_current_project_metadata(monkeypatch):
_patch_project_scadas(monkeypatch)
query_mock = AsyncMock(
return_value={
PROJECT_SCADA["device_id"]: [{"time": START_TIME, "value": 26.5}]
}
)
monkeypatch.setattr(
composite_queries.ScadaRepository,
"get_scada_field_by_id_time_range",
query_mock,
)
result = asyncio.run(
composite_queries.TimeseriesAnalysisService.get_element_associated_scada_data(
object(),
object(),
"J1",
START_TIME,
END_TIME,
)
)
assert result == {"J1": [{"time": START_TIME, "value": 26.5}]}
def test_history_uses_current_project_metadata(monkeypatch):
postgres = object()
mappings = AsyncMock(return_value=[PROJECT_SCADA.copy()])
monkeypatch.setattr(history.ScadaInfoRepository, "get_scadas_for_elements", mappings)
monkeypatch.setattr(history.ScadaRepository, "get_scada_by_ids_time_range", AsyncMock(return_value=[{
"time": START_TIME, "device_id": PROJECT_SCADA["device_id"],
"monitored_value": 26.5, "cleaned_value": 26.0,
}]))
result = asyncio.run(history.TimeseriesHistoryService.query(object(), postgres, ElementHistoryQuery(
start_time=START_TIME, end_time=END_TIME,
elements=[{"element_id": "J1", "element_type": "junction", "device_ids": [PROJECT_SCADA["device_id"]]}],
)))
assert mappings.await_args.args == (postgres, ["J1"], [])
assert len(result.series) == 2
assert all(item.device_id == PROJECT_SCADA["device_id"] and item.element_id == "J1" for item in result.series)
assert [item.points[0].value for item in result.series] == [26.5, 26.0]
def test_scada_info_endpoint_uses_current_project_connection(monkeypatch):