Files
Remote-Terminal-for-MeshCore/app/routers/health.py
2026-03-09 23:07:34 -07:00

78 lines
2.5 KiB
Python

import os
from typing import Any
from fastapi import APIRouter
from pydantic import BaseModel
from app.config import settings
from app.repository import RawPacketRepository
from app.services.radio_runtime import radio_runtime as radio_manager
router = APIRouter(tags=["health"])
class HealthResponse(BaseModel):
status: str
radio_connected: bool
radio_initializing: bool = False
connection_info: str | None
database_size_mb: float
oldest_undecrypted_timestamp: int | None
fanout_statuses: dict[str, dict[str, str]] = {}
bots_disabled: bool = False
async def build_health_data(radio_connected: bool, connection_info: str | None) -> dict:
"""Build the health status payload used by REST endpoint and WebSocket broadcasts."""
db_size_mb = 0.0
try:
db_size_bytes = os.path.getsize(settings.database_path)
db_size_mb = round(db_size_bytes / (1024 * 1024), 2)
except OSError:
pass
oldest_ts = None
try:
oldest_ts = await RawPacketRepository.get_oldest_undecrypted()
except RuntimeError:
pass # Database not connected
# Fanout module statuses
fanout_statuses: dict[str, Any] = {}
try:
from app.fanout.manager import fanout_manager
fanout_statuses = fanout_manager.get_statuses()
except Exception:
pass
setup_in_progress = getattr(radio_manager, "is_setup_in_progress", False)
if not isinstance(setup_in_progress, bool):
setup_in_progress = False
setup_complete = getattr(radio_manager, "is_setup_complete", radio_connected)
if not isinstance(setup_complete, bool):
setup_complete = radio_connected
if not radio_connected:
setup_complete = False
radio_initializing = bool(radio_connected and (setup_in_progress or not setup_complete))
return {
"status": "ok" if radio_connected and not radio_initializing else "degraded",
"radio_connected": radio_connected,
"radio_initializing": radio_initializing,
"connection_info": connection_info,
"database_size_mb": db_size_mb,
"oldest_undecrypted_timestamp": oldest_ts,
"fanout_statuses": fanout_statuses,
"bots_disabled": settings.disable_bots,
}
@router.get("/health", response_model=HealthResponse)
async def healthcheck() -> HealthResponse:
"""Check if the API is running and if the radio is connected."""
data = await build_health_data(radio_manager.is_connected, radio_manager.connection_info)
return HealthResponse(**data)