import os import asyncio import multiprocessing as mp from fastapi import APIRouter router = APIRouter() @router.get("/info") async def get_system_info(): """Return system info: CPU cores, GPU availability, parallel backend.""" cpu_cores = mp.cpu_count() or 1 # Check Ray ray_available = False ray_initialized = False try: from app.services.parallel_coverage_service import RAY_AVAILABLE ray_available = RAY_AVAILABLE if ray_available: import ray ray_initialized = ray.is_initialized() except Exception: pass # Check GPU via gpu_service from app.services.gpu_service import gpu_service gpu_info = gpu_service.get_info() # Determine parallel backend if ray_available: parallel_backend = "ray" elif cpu_cores > 1: parallel_backend = "process_pool" else: parallel_backend = "sequential" return { "cpu_cores": cpu_cores, "parallel_workers": min(cpu_cores, 14), "parallel_backend": parallel_backend, "ray_available": ray_available, "ray_initialized": ray_initialized, "gpu": gpu_info, "gpu_available": gpu_info.get("available", False), } @router.post("/shutdown") async def shutdown(): """Graceful shutdown endpoint. Kills worker processes and exits.""" from app.services.parallel_coverage_service import _kill_worker_processes killed = _kill_worker_processes() # Schedule hard exit after response is sent loop = asyncio.get_event_loop() loop.call_later(0.5, lambda: os._exit(0)) return {"status": "shutting down", "workers_killed": killed}