更新tjwater-cli network参数;更新metadb health方法
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import logging
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query, Path
|
||||
import psycopg
|
||||
from psycopg import AsyncConnection
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
@@ -58,6 +59,7 @@ async def get_project_metadata(
|
||||
code=project.code,
|
||||
description=project.description,
|
||||
gs_workspace=project.gs_workspace,
|
||||
map_extent=project.map_extent,
|
||||
status=project.status,
|
||||
project_role=ctx.project_role,
|
||||
geoserver=geoserver_payload,
|
||||
@@ -110,7 +112,23 @@ async def project_db_health(
|
||||
|
||||
检查PostgreSQL和TimescaleDB数据库的连接状态
|
||||
"""
|
||||
await pg_session.execute(text("SELECT 1"))
|
||||
async with ts_conn.cursor() as cur:
|
||||
await cur.execute("SELECT 1")
|
||||
try:
|
||||
await pg_session.execute(text("SELECT 1"))
|
||||
except SQLAlchemyError as exc:
|
||||
logger.error("Project PostgreSQL health check failed", exc_info=True)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail=f"Project PostgreSQL health check failed: {exc}",
|
||||
) from exc
|
||||
|
||||
try:
|
||||
async with ts_conn.cursor() as cur:
|
||||
await cur.execute("SELECT 1")
|
||||
except psycopg.Error as exc:
|
||||
logger.error("Project TimescaleDB health check failed", exc_info=True)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail=f"Project TimescaleDB health check failed: {exc}",
|
||||
) from exc
|
||||
|
||||
return {"postgres": "ok", "timescale": "ok"}
|
||||
|
||||
@@ -5,10 +5,10 @@ from pydantic import BaseModel
|
||||
|
||||
|
||||
class GeoServerConfigResponse(BaseModel):
|
||||
gs_base_url: Optional[str]
|
||||
gs_admin_user: Optional[str]
|
||||
gs_base_url: Optional[str] = None
|
||||
gs_admin_user: Optional[str] = None
|
||||
gs_datastore_name: str
|
||||
default_extent: Optional[dict]
|
||||
default_extent: Optional[dict] = None
|
||||
srid: int
|
||||
|
||||
|
||||
@@ -16,19 +16,19 @@ class ProjectMetaResponse(BaseModel):
|
||||
project_id: UUID
|
||||
name: str
|
||||
code: str
|
||||
description: Optional[str]
|
||||
description: Optional[str] = None
|
||||
gs_workspace: str
|
||||
map_extent: Optional[dict]
|
||||
map_extent: Optional[dict] = None
|
||||
status: str
|
||||
project_role: str
|
||||
geoserver: Optional[GeoServerConfigResponse]
|
||||
geoserver: Optional[GeoServerConfigResponse] = None
|
||||
|
||||
|
||||
class ProjectSummaryResponse(BaseModel):
|
||||
project_id: UUID
|
||||
name: str
|
||||
code: str
|
||||
description: Optional[str]
|
||||
description: Optional[str] = None
|
||||
gs_workspace: str
|
||||
status: str
|
||||
project_role: str
|
||||
|
||||
@@ -119,7 +119,7 @@ def load_auth_context(auth_stdin: bool = False) -> AuthContext:
|
||||
project_id=_pick(raw, "project_id", "projectId", "x_project_id"),
|
||||
user_id=_pick(raw, "user_id", "userId", "x_user_id"),
|
||||
username=_pick(raw, "username", "preferred_username"),
|
||||
network="tjwater",
|
||||
network=_pick(raw, "network", "project_code", "projectCode", "project"),
|
||||
headers={str(key): str(value) for key, value in headers.items()},
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
from types import SimpleNamespace
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from tests.conftest import build_test_app, install_stub, load_module_from_path
|
||||
|
||||
|
||||
def _load_meta_module(monkeypatch):
|
||||
install_stub(monkeypatch, "app.auth", package=True)
|
||||
install_stub(
|
||||
monkeypatch,
|
||||
"app.auth.project_dependencies",
|
||||
{
|
||||
"ProjectContext": object,
|
||||
"get_project_context": lambda: None,
|
||||
"get_project_pg_session": lambda: None,
|
||||
"get_project_timescale_connection": lambda: None,
|
||||
"get_metadata_repository": lambda: None,
|
||||
},
|
||||
)
|
||||
install_stub(
|
||||
monkeypatch,
|
||||
"app.auth.metadata_dependencies",
|
||||
{"get_current_metadata_user": lambda: None},
|
||||
)
|
||||
return load_module_from_path(
|
||||
"tests_meta_endpoints_module",
|
||||
"app/api/v1/endpoints/meta.py",
|
||||
)
|
||||
|
||||
|
||||
def test_meta_project_returns_map_extent(monkeypatch):
|
||||
module = _load_meta_module(monkeypatch)
|
||||
project_id = uuid4()
|
||||
repo = SimpleNamespace(
|
||||
get_project_by_id=lambda _project_id: None,
|
||||
get_geoserver_config=lambda _project_id: None,
|
||||
)
|
||||
|
||||
async def get_project_by_id(_project_id):
|
||||
return SimpleNamespace(
|
||||
id=project_id,
|
||||
name="Demo Project",
|
||||
code="demo",
|
||||
description="desc",
|
||||
gs_workspace="workspace",
|
||||
map_extent={"xmin": 1, "ymin": 2, "xmax": 3, "ymax": 4},
|
||||
status="active",
|
||||
)
|
||||
|
||||
async def get_geoserver_config(_project_id):
|
||||
return None
|
||||
|
||||
repo.get_project_by_id = get_project_by_id
|
||||
repo.get_geoserver_config = get_geoserver_config
|
||||
|
||||
app = build_test_app(module.router, "/api/v1")
|
||||
app.dependency_overrides[module.get_project_context] = lambda: SimpleNamespace(
|
||||
project_id=project_id,
|
||||
project_role="editor",
|
||||
)
|
||||
app.dependency_overrides[module.get_metadata_repository] = lambda: repo
|
||||
client = TestClient(app)
|
||||
|
||||
response = client.get("/api/v1/meta/project")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["map_extent"] == {"xmin": 1, "ymin": 2, "xmax": 3, "ymax": 4}
|
||||
|
||||
|
||||
def test_meta_db_health_returns_503_for_postgres_errors(monkeypatch):
|
||||
module = _load_meta_module(monkeypatch)
|
||||
|
||||
class BrokenSession:
|
||||
async def execute(self, _query):
|
||||
raise SQLAlchemyError("pg unavailable")
|
||||
|
||||
class DummyTimescaleConnection:
|
||||
def cursor(self):
|
||||
raise AssertionError("timescale should not be queried after postgres failure")
|
||||
|
||||
app = build_test_app(module.router, "/api/v1")
|
||||
app.dependency_overrides[module.get_project_pg_session] = lambda: BrokenSession()
|
||||
app.dependency_overrides[module.get_project_timescale_connection] = lambda: DummyTimescaleConnection()
|
||||
client = TestClient(app)
|
||||
|
||||
response = client.get("/api/v1/meta/db/health")
|
||||
|
||||
assert response.status_code == 503
|
||||
assert response.json()["detail"] == "Project PostgreSQL health check failed: pg unavailable"
|
||||
Reference in New Issue
Block a user