"""Execute API endpoint for SQL configuration execution. This module provides the /execute endpoint for executing SQL configuration. """ import uuid from typing import Dict, Any from fastapi import APIRouter, HTTPException, status from loguru import logger from app.models.request import ExecuteRequest from app.models.response import ExecuteResponse, ErrorResponse from app.core.executor import ConfigExecutor # Create router router = APIRouter() # In-memory storage for SQL lists (should use Redis/database in production) _session_sql_store: Dict[str, list] = {} def store_session_sql(session_id: str, sql_list: list) -> None: """Store SQL list for a session. Args: session_id: Session ID sql_list: List of SQL statements """ _session_sql_store[session_id] = sql_list logger.debug(f"Stored {len(sql_list)} SQL statements for session {session_id}") def get_session_sql(session_id: str) -> list: """Retrieve SQL list for a session. Args: session_id: Session ID Returns: List of SQL statements (empty list if not found) """ sql_list = _session_sql_store.get(session_id, []) logger.debug(f"Retrieved {len(sql_list)} SQL statements for session {session_id}") return sql_list @router.post( "/execute", response_model=ExecuteResponse, responses={ 400: {"model": ErrorResponse, "description": "Invalid request"}, 500: {"model": ErrorResponse, "description": "Internal server error"} }, summary="Execute SQL configuration", description="Execute SQL configuration after user confirmation" ) async def execute_config(request: ExecuteRequest) -> ExecuteResponse: """Execute SQL configuration after user confirmation. This endpoint executes the SQL statements associated with the session. User must set confirmed=True to proceed with execution. Args: request: ExecuteRequest with session_id, confirmed, and backup_enabled Returns: ExecuteResponse with execution_id, status, and message Raises: HTTPException: 400 if not confirmed or invalid, 500 for execution errors """ # Generate execution ID execution_id = str(uuid.uuid4()) try: # Check user confirmation if not request.confirmed: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail={ "code": "NOT_CONFIRMED", "message": "User must confirm execution by setting confirmed=True", "session_id": request.session_id, "execution_id": execution_id } ) logger.info(f"[{request.session_id}] Processing execute request") # Retrieve SQL list for session sql_list = get_session_sql(request.session_id) if not sql_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail={ "code": "NO_SQL_FOUND", "message": "No SQL statements found for this session", "session_id": request.session_id, "execution_id": execution_id } ) logger.info(f"[{request.session_id}] Retrieved {len(sql_list)} SQL statements") # Create executor executor = ConfigExecutor() # Execute configuration result = executor.execute_config(sql_list, request.session_id) if result["success"]: logger.success( f"[{request.session_id}] Execution completed: {result['message']}" ) return ExecuteResponse( execution_id=execution_id, status="success", message=result["message"] ) else: logger.error( f"[{request.session_id}] Execution failed: {result['failed']}" ) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail={ "code": "EXECUTION_FAILED", "message": result["message"], "error": result["failed"], "session_id": request.session_id, "execution_id": execution_id } ) except HTTPException: # Re-raise HTTP exceptions raise except Exception as e: logger.error(f"[{request.session_id}] Execution failed: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail={ "code": "EXECUTION_ERROR", "message": f"Failed to execute config: {str(e)}", "session_id": request.session_id, "execution_id": execution_id } )