refactor(db)!: adopt project-routed pooled databases
Reorganize WNDB by responsibility and remove legacy scheme endpoints.\n\nRoute analysis and time-series access through project pools, preserve transactional realtime replacement, and refresh GIS materialized views after writes.\n\nAdd database architecture documentation, live pooling coverage, API contract updates, and executable container verification.\n\nBREAKING CHANGE: legacy scheme APIs and flat app.native.wndb module imports are removed.
This commit is contained in:
@@ -10,12 +10,10 @@ from fastapi import APIRouter, FastAPI, Query
|
||||
from fastapi.routing import APIRoute
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.api.v1.endpoints import schemes as schemes_endpoint
|
||||
from app.api.v1.endpoints import simulation as simulation_endpoint
|
||||
from app.api.pagination import PaginatedList
|
||||
from app.api.v1.rest_router import api_router, build_rest_router
|
||||
from app.api.v1.router import api_router as source_api_router
|
||||
from app.auth.metadata_dependencies import get_current_metadata_user
|
||||
from app.auth.project_dependencies import (
|
||||
ProjectContext,
|
||||
get_project_business_routing,
|
||||
@@ -173,12 +171,6 @@ def test_rest_contract_uses_header_project_context() -> None:
|
||||
assert "network" not in schema.get("properties", {})
|
||||
assert "network_name" not in schema.get("properties", {})
|
||||
|
||||
placement_schema = document["components"]["schemas"][
|
||||
"PressureSensorPlacementRest"
|
||||
]
|
||||
assert "name" not in placement_schema["properties"]
|
||||
assert "username" not in placement_schema["properties"]
|
||||
|
||||
assert "/api/v1/burst-analysis" not in document["paths"]
|
||||
assert "/api/v1/getpipeproperties/" not in document["paths"]
|
||||
|
||||
@@ -294,54 +286,10 @@ def test_sensor_placement_excel_export_is_post() -> None:
|
||||
if isinstance(route, APIRoute)
|
||||
}
|
||||
assert methods_by_path[
|
||||
"/sensor-placement-schemes/{scheme_id}/exports/excel"
|
||||
"/sensor-placement-runs/{run_id}/exports/excel"
|
||||
] == {"POST"}
|
||||
|
||||
|
||||
def test_rest_runtime_consumes_injected_project_context(monkeypatch) -> None:
|
||||
captured: dict[str, object] = {}
|
||||
|
||||
def fake_get_all_schemes(network, scheme_type=None, query_date=None):
|
||||
captured.update(
|
||||
network=network,
|
||||
scheme_type=scheme_type,
|
||||
query_date=query_date,
|
||||
business_dsn=get_project_pgconn_string(network),
|
||||
)
|
||||
return [{"scheme_name": "burst_case", "scheme_type": scheme_type}]
|
||||
|
||||
monkeypatch.setattr(
|
||||
schemes_endpoint,
|
||||
"get_all_schemes",
|
||||
fake_get_all_schemes,
|
||||
)
|
||||
app = FastAPI(redirect_slashes=False)
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
project_context = ProjectContext(
|
||||
project_id=uuid4(),
|
||||
project_code="fengyang",
|
||||
user_id=uuid4(),
|
||||
project_role="viewer",
|
||||
)
|
||||
_override_project_routing(app, project_context)
|
||||
|
||||
response = TestClient(app, raise_server_exceptions=False).get(
|
||||
"/api/v1/schemes",
|
||||
params={"scheme_type": "burst_analysis"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert captured == {
|
||||
"network": "fengyang",
|
||||
"scheme_type": "burst_analysis",
|
||||
"query_date": None,
|
||||
"business_dsn": "postgresql://user:password@biz/fengyang",
|
||||
}
|
||||
assert response.json()["items"] == [
|
||||
{"scheme_name": "burst_case", "scheme_type": "burst_analysis"}
|
||||
]
|
||||
|
||||
|
||||
def test_rest_runtime_wraps_handler_paginated_list() -> None:
|
||||
source_router = APIRouter()
|
||||
|
||||
@@ -370,51 +318,6 @@ def test_rest_runtime_wraps_handler_paginated_list() -> None:
|
||||
}
|
||||
|
||||
|
||||
def test_sensor_placement_body_uses_authenticated_project_and_user(
|
||||
monkeypatch,
|
||||
) -> None:
|
||||
captured: dict[str, object] = {}
|
||||
|
||||
def fake_pressure_sensor_placement_kmeans(**kwargs):
|
||||
captured.update(kwargs)
|
||||
|
||||
monkeypatch.setattr(
|
||||
simulation_endpoint,
|
||||
"pressure_sensor_placement_kmeans",
|
||||
fake_pressure_sensor_placement_kmeans,
|
||||
)
|
||||
app = FastAPI(redirect_slashes=False)
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
project_context = ProjectContext(
|
||||
project_id=uuid4(),
|
||||
project_code="project_a",
|
||||
user_id=uuid4(),
|
||||
project_role="member",
|
||||
)
|
||||
_override_project_routing(app, project_context)
|
||||
app.dependency_overrides[get_current_metadata_user] = lambda: type(
|
||||
"User", (), {"username": "alice"}
|
||||
)()
|
||||
|
||||
response = TestClient(app, raise_server_exceptions=False).post(
|
||||
"/api/v1/pressure-sensor-placement-kmeans",
|
||||
json={
|
||||
"scheme_name": "placement_01",
|
||||
"sensor_number": 5,
|
||||
"min_diameter": 100,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert captured == {
|
||||
"name": "project_a",
|
||||
"scheme_name": "placement_01",
|
||||
"sensor_number": 5,
|
||||
"min_diameter": 100,
|
||||
"username": "alice",
|
||||
}
|
||||
|
||||
|
||||
def test_rest_runtime_json_encodes_untyped_datetime_response() -> None:
|
||||
source_router = APIRouter()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user