231 lines
7.9 KiB
Python
231 lines
7.9 KiB
Python
"""
|
||
Analysis Sessions API endpoints.
|
||
|
||
Управление сессиями анализа (создание, получение, удаление).
|
||
"""
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||
from typing import Optional
|
||
from app.models.analysis import SessionCreate, SessionResponse, SessionList, SessionUpdate
|
||
from app.interfaces.db_api_client import DBApiClient
|
||
from app.dependencies import get_db_client, get_current_user
|
||
import httpx
|
||
import logging
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
router = APIRouter(prefix="/analysis", tags=["analysis"])
|
||
|
||
|
||
@router.post("/sessions", response_model=SessionResponse, status_code=status.HTTP_201_CREATED)
|
||
async def create_session(
|
||
session: SessionCreate,
|
||
current_user: dict = Depends(get_current_user),
|
||
db_client: DBApiClient = Depends(get_db_client)
|
||
):
|
||
"""
|
||
Создать новую сессию анализа.
|
||
|
||
Args:
|
||
session: Данные сессии (environment, api_mode, request, response, annotations)
|
||
|
||
Returns:
|
||
SessionResponse: Созданная сессия с session_id
|
||
"""
|
||
user_id = current_user["user_id"]
|
||
|
||
try:
|
||
created_session = await db_client.save_session(user_id, session)
|
||
return created_session
|
||
except httpx.HTTPStatusError as e:
|
||
if e.response.status_code == 404:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail="User not found"
|
||
)
|
||
elif e.response.status_code == 400:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_400_BAD_REQUEST,
|
||
detail="Invalid session data format"
|
||
)
|
||
logger.error(f"Failed to create session: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||
detail="Failed to create session in DB API"
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"Unexpected error creating session: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||
detail="Internal server error"
|
||
)
|
||
|
||
|
||
@router.get("/sessions", response_model=SessionList)
|
||
async def get_sessions(
|
||
environment: Optional[str] = Query(None, description="Фильтр по окружению (ift/psi/prod)"),
|
||
limit: int = Query(50, ge=1, le=200, description="Лимит результатов"),
|
||
offset: int = Query(0, ge=0, description="Смещение для пагинации"),
|
||
current_user: dict = Depends(get_current_user),
|
||
db_client: DBApiClient = Depends(get_db_client)
|
||
):
|
||
"""
|
||
Получить список сессий пользователя.
|
||
|
||
Args:
|
||
environment: Фильтр по окружению (опционально)
|
||
limit: Лимит результатов (default: 50, max: 200)
|
||
offset: Смещение для пагинации (default: 0)
|
||
|
||
Returns:
|
||
SessionList: Список сессий с total count
|
||
"""
|
||
user_id = current_user["user_id"]
|
||
|
||
try:
|
||
sessions = await db_client.get_sessions(user_id, environment, limit, offset)
|
||
return sessions
|
||
except httpx.HTTPStatusError as e:
|
||
if e.response.status_code == 404:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail="User not found"
|
||
)
|
||
logger.error(f"Failed to get sessions: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||
detail="Failed to retrieve sessions from DB API"
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"Unexpected error getting sessions: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||
detail="Internal server error"
|
||
)
|
||
|
||
|
||
@router.get("/sessions/{session_id}", response_model=SessionResponse)
|
||
async def get_session(
|
||
session_id: str,
|
||
current_user: dict = Depends(get_current_user),
|
||
db_client: DBApiClient = Depends(get_db_client)
|
||
):
|
||
"""
|
||
Получить конкретную сессию по ID.
|
||
|
||
Args:
|
||
session_id: UUID сессии
|
||
|
||
Returns:
|
||
SessionResponse: Полная информация о сессии
|
||
"""
|
||
user_id = current_user["user_id"]
|
||
|
||
try:
|
||
session = await db_client.get_session(user_id, session_id)
|
||
return session
|
||
except httpx.HTTPStatusError as e:
|
||
if e.response.status_code == 404:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail="Session not found"
|
||
)
|
||
logger.error(f"Failed to get session {session_id}: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||
detail="Failed to retrieve session from DB API"
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"Unexpected error getting session {session_id}: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||
detail="Internal server error"
|
||
)
|
||
|
||
|
||
@router.patch("/sessions/{session_id}", response_model=SessionResponse)
|
||
async def update_session(
|
||
session_id: str,
|
||
update_data: SessionUpdate,
|
||
current_user: dict = Depends(get_current_user),
|
||
db_client: DBApiClient = Depends(get_db_client)
|
||
):
|
||
"""
|
||
Обновить аннотации сессии (например, после ревью).
|
||
|
||
Полностью заменяет существующие аннотации новыми.
|
||
|
||
Args:
|
||
session_id: UUID сессии
|
||
update_data: Новые аннотации с ключами в виде числовых строк ('0', '1', ...)
|
||
|
||
Returns:
|
||
SessionResponse: Обновленная сессия
|
||
"""
|
||
user_id = current_user["user_id"]
|
||
|
||
try:
|
||
updated_session = await db_client.update_session(user_id, session_id, update_data)
|
||
return updated_session
|
||
except httpx.HTTPStatusError as e:
|
||
if e.response.status_code == 404:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail="Session not found"
|
||
)
|
||
elif e.response.status_code == 400:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_400_BAD_REQUEST,
|
||
detail="Invalid annotations format"
|
||
)
|
||
logger.error(f"Failed to update session {session_id}: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||
detail="Failed to update session in DB API"
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"Unexpected error updating session {session_id}: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||
detail="Internal server error"
|
||
)
|
||
|
||
|
||
@router.delete("/sessions/{session_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||
async def delete_session(
|
||
session_id: str,
|
||
current_user: dict = Depends(get_current_user),
|
||
db_client: DBApiClient = Depends(get_db_client)
|
||
):
|
||
"""
|
||
Удалить сессию.
|
||
|
||
Args:
|
||
session_id: UUID сессии
|
||
|
||
Returns:
|
||
204 No Content при успехе
|
||
"""
|
||
user_id = current_user["user_id"]
|
||
|
||
try:
|
||
await db_client.delete_session(user_id, session_id)
|
||
return None
|
||
except httpx.HTTPStatusError as e:
|
||
if e.response.status_code == 404:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail="Session not found"
|
||
)
|
||
logger.error(f"Failed to delete session {session_id}: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||
detail="Failed to delete session in DB API"
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"Unexpected error deleting session {session_id}: {e}")
|
||
raise HTTPException(
|
||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||
detail="Internal server error"
|
||
)
|