This commit is contained in:
2026-07-05 21:27:23 +09:00
parent 23d907265a
commit 3abc2edba6
83 changed files with 10351 additions and 1217 deletions
+133
View File
@@ -0,0 +1,133 @@
"""B05 경로 설계 FastAPI 라우터."""
import asyncio
import logging
from pathlib import Path
from uuid import UUID
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
from B05_wf2_Route.B05_wf2_Route_Engine import run_route_design
from B05_wf2_Route.B05_wf2_Route_Repository import (
confirm_route,
create_route,
create_route_statistics,
get_latest_route,
insert_route_points,
)
from B05_wf2_Route.B05_wf2_Route_Schema import (
RouteConfirmResponse,
RouteSolveRequest,
RouteSolveResponse,
)
from common_util.common_util_storage import resolve_stored_project_path
from config.config_db import get_db_pool
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/projects", tags=["B05 Route Design"])
@router.post("/{project_id}/route/solve", response_model=RouteSolveResponse)
async def solve_route(
project_id: UUID, request: RouteSolveRequest
) -> RouteSolveResponse | JSONResponse:
"""경로 탐색을 실행하고 결과를 GeoJSON 저장 + DB 기록한다."""
pool = get_db_pool()
try:
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
# 무거운 경로 탐색은 이벤트 루프를 막지 않도록 별도 스레드에서 실행.
design = await asyncio.to_thread(
run_route_design,
project_root,
request.filter_key,
request.method,
request.smooth,
request.points_data(),
request.options(),
request.algorithm,
)
solver = design["solver_result"]
metrics = solver["metrics"]
await connection.begin()
try:
route_id = await create_route(
connection,
project_id=project_id,
surface_model_id=request.surface_model_id,
total_length_m=metrics.get("length_m"),
start_chainage_m=0.0,
end_chainage_m=metrics.get("length_m"),
grade_percent=design["grade_percent"],
constraints=design["constraints"],
algorithm_params=design["algorithm_params"],
route_data_path=design["route_data_path"],
)
await insert_route_points(connection, route_id, design["render_points"])
stats = design["statistics"]
await create_route_statistics(
connection,
route_id=route_id,
min_slope=stats["min_slope"],
max_slope=stats["max_slope"],
mean_slope=stats["mean_slope"],
cost_score=stats["cost_score"],
)
await connection.commit()
except Exception:
await connection.rollback()
raise
return RouteSolveResponse(
project_id=str(project_id),
route_id=route_id,
total_length_m=metrics.get("length_m", 0.0),
metrics=metrics,
required_points_ok=solver["required_points_ok"],
route_data_path=design["route_data_path"],
)
except LookupError as exc:
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
except FileNotFoundError as exc:
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
except (OSError, ValueError) as exc:
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
except Exception:
logger.exception("B05 경로 탐색 실패: project_id=%s", project_id)
return JSONResponse(
status_code=500,
content={"status": "error", "message": "경로 탐색 처리 중 오류가 발생했습니다."},
)
@router.post("/{project_id}/route/confirm", response_model=RouteConfirmResponse)
async def confirm_latest_route(project_id: UUID) -> RouteConfirmResponse | JSONResponse:
"""프로젝트의 최신 경로를 확정(CONFIRMED)한다."""
pool = get_db_pool()
try:
async with pool.acquire() as connection:
latest = await get_latest_route(connection, project_id)
if not latest:
return JSONResponse(
status_code=404,
content={"status": "error", "message": "확정할 경로가 없습니다."},
)
await connection.begin()
try:
await confirm_route(connection, latest["id"])
await connection.commit()
except Exception:
await connection.rollback()
raise
return RouteConfirmResponse(project_id=str(project_id), route_id=latest["id"])
except Exception:
logger.exception("B05 경로 확정 실패: project_id=%s", project_id)
return JSONResponse(
status_code=500,
content={"status": "error", "message": "경로 확정 처리 중 오류가 발생했습니다."},
)