135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
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
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.auth.project_dependencies import (
|
|
ProjectContext,
|
|
get_project_context,
|
|
get_project_pg_session,
|
|
get_project_timescale_connection,
|
|
get_metadata_repository,
|
|
)
|
|
from app.auth.metadata_dependencies import get_current_metadata_user
|
|
from app.core.config import settings
|
|
from app.domain.schemas.metadata import (
|
|
GeoServerConfigResponse,
|
|
ProjectMetaResponse,
|
|
ProjectSummaryResponse,
|
|
)
|
|
from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository
|
|
|
|
router = APIRouter()
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@router.get("/meta/project", summary="获取项目元数据", description="获取当前项目的元数据和配置信息", response_model=ProjectMetaResponse)
|
|
async def get_project_metadata(
|
|
ctx: ProjectContext = Depends(get_project_context),
|
|
metadata_repo: MetadataRepository = Depends(get_metadata_repository),
|
|
):
|
|
"""
|
|
获取项目元数据
|
|
|
|
返回当前项目的完整元数据,包括项目基本信息和GeoServer配置
|
|
"""
|
|
project = await metadata_repo.get_project_by_id(ctx.project_id)
|
|
if not project:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
|
|
)
|
|
geoserver = await metadata_repo.get_geoserver_config(ctx.project_id)
|
|
geoserver_payload = (
|
|
GeoServerConfigResponse(
|
|
gs_base_url=geoserver.gs_base_url,
|
|
gs_admin_user=geoserver.gs_admin_user,
|
|
gs_datastore_name=geoserver.gs_datastore_name,
|
|
default_extent=geoserver.default_extent,
|
|
srid=geoserver.srid,
|
|
)
|
|
if geoserver
|
|
else None
|
|
)
|
|
return ProjectMetaResponse(
|
|
project_id=project.id,
|
|
name=project.name,
|
|
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,
|
|
)
|
|
|
|
|
|
@router.get("/meta/projects", summary="列出用户项目", description="获取当前用户有权限的所有项目列表", response_model=list[ProjectSummaryResponse])
|
|
async def list_user_projects(
|
|
current_user=Depends(get_current_metadata_user),
|
|
metadata_repo: MetadataRepository = Depends(get_metadata_repository),
|
|
):
|
|
"""
|
|
列出用户的所有项目
|
|
|
|
返回当前用户有权限访问的项目摘要列表
|
|
"""
|
|
try:
|
|
projects = await metadata_repo.list_projects_for_user(current_user.id)
|
|
except SQLAlchemyError as exc:
|
|
logger.error(
|
|
"Metadata DB error while listing projects for user %s",
|
|
current_user.id,
|
|
exc_info=True,
|
|
)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail=f"Metadata database error: {exc}",
|
|
) from exc
|
|
return [
|
|
ProjectSummaryResponse(
|
|
project_id=project.project_id,
|
|
name=project.name,
|
|
code=project.code,
|
|
description=project.description,
|
|
gs_workspace=project.gs_workspace,
|
|
status=project.status,
|
|
project_role=project.project_role,
|
|
)
|
|
for project in projects
|
|
]
|
|
|
|
|
|
@router.get("/meta/db/health", summary="检查数据库健康状态", description="检查项目数据库连接的健康状况")
|
|
async def project_db_health(
|
|
pg_session: AsyncSession = Depends(get_project_pg_session),
|
|
ts_conn: AsyncConnection = Depends(get_project_timescale_connection),
|
|
):
|
|
"""
|
|
检查数据库健康状态
|
|
|
|
检查PostgreSQL和TimescaleDB数据库的连接状态
|
|
"""
|
|
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"}
|