import logging from fastapi import APIRouter, Depends, HTTPException, status, Query, Path import psycopg from psycopg import AsyncConnection from app.auth.project_dependencies import ( ProjectContext, get_project_context, get_project_pg_connection, 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 ( ProjectMetaResponse, ProjectSummaryResponse, ) from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository router = APIRouter() logger = logging.getLogger(__name__) @router.get("/projects/current/metadata", summary="获取项目元数据", description="获取当前项目的元数据和配置信息", response_model=ProjectMetaResponse) async def get_project_metadata( ctx: ProjectContext = Depends(get_project_context), metadata_repo: MetadataRepository = Depends(get_metadata_repository), ): """ 获取项目元数据 返回当前项目的完整元数据,包括项目基本信息和项目权限 """ 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" ) 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, ) @router.get("/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("/projects/current/database-health", summary="检查数据库健康状态", description="检查项目数据库连接的健康状况") async def project_db_health( pg_conn: AsyncConnection = Depends(get_project_pg_connection), ts_conn: AsyncConnection = Depends(get_project_timescale_connection), ): """ 检查数据库健康状态 检查PostgreSQL和TimescaleDB数据库的连接状态 """ try: async with pg_conn.cursor() as cur: await cur.execute("SELECT 1") await cur.fetchone() except psycopg.Error 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"}