165 lines
6.6 KiB
Python
165 lines
6.6 KiB
Python
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Body, Header
|
|
|
|
from app.schemas.common import ApiResponse
|
|
from app.services.build_info_service import get_runtime_build_info
|
|
from app.services.cluster_runtime_service import get_cluster_snapshot
|
|
from app.services.debug_event_service import get_debug_diagnosis, get_debug_event_overview, get_debug_handoff_report, ingest_debug_event, list_debug_events
|
|
from app.services.detect_job_service import get_detect_queue_health
|
|
from app.services.runtime_control_service import runtime_action
|
|
from app.services.runtime_status_service import get_runtime_preflight, get_runtime_status
|
|
from app.services.sync_push_service import (
|
|
ack_detect_task_projection,
|
|
export_detect_task_projection,
|
|
ingest_runtime_projection,
|
|
)
|
|
from app.services.sync_record_service import get_sync_summary, list_sync_records
|
|
|
|
router = APIRouter(tags=["runtime"])
|
|
|
|
|
|
@router.get("/runtime/status", response_model=ApiResponse)
|
|
def runtime_status() -> ApiResponse:
|
|
return ApiResponse(data=get_runtime_status())
|
|
|
|
|
|
@router.get("/runtime/readiness", response_model=ApiResponse)
|
|
def runtime_readiness() -> ApiResponse:
|
|
return ApiResponse(data=(get_runtime_status().get("readiness") or {}))
|
|
|
|
|
|
@router.get("/runtime/preflight", response_model=ApiResponse)
|
|
def runtime_preflight() -> ApiResponse:
|
|
return ApiResponse(data=get_runtime_preflight())
|
|
|
|
|
|
@router.get("/runtime/cluster", response_model=ApiResponse)
|
|
def runtime_cluster() -> ApiResponse:
|
|
return ApiResponse(data=get_cluster_snapshot())
|
|
|
|
|
|
@router.get("/runtime/build-info", response_model=ApiResponse)
|
|
def runtime_build_info() -> ApiResponse:
|
|
return ApiResponse(data=get_runtime_build_info())
|
|
|
|
|
|
@router.get("/runtime/sync-summary", response_model=ApiResponse)
|
|
def runtime_sync_summary() -> ApiResponse:
|
|
return ApiResponse(data=get_sync_summary())
|
|
|
|
|
|
@router.get("/runtime/sync-records", response_model=ApiResponse)
|
|
def runtime_sync_records(limit: int = 20) -> ApiResponse:
|
|
return ApiResponse(data={"records": list_sync_records(limit=limit)})
|
|
|
|
|
|
@router.get("/runtime/debug-events", response_model=ApiResponse)
|
|
def runtime_debug_events(
|
|
limit: int = 50,
|
|
service: Optional[str] = None,
|
|
event_type: Optional[str] = None,
|
|
source_region: Optional[str] = None,
|
|
level: Optional[str] = None,
|
|
before_id: Optional[int] = None,
|
|
after_id: Optional[int] = None,
|
|
created_after: Optional[str] = None,
|
|
) -> ApiResponse:
|
|
return ApiResponse(
|
|
data=list_debug_events(
|
|
limit=limit,
|
|
service=service,
|
|
event_type=event_type,
|
|
source_region=source_region,
|
|
level=level,
|
|
before_id=before_id,
|
|
after_id=after_id,
|
|
created_after=created_after,
|
|
)
|
|
)
|
|
|
|
|
|
@router.get("/runtime/debug-overview", response_model=ApiResponse)
|
|
def runtime_debug_overview(window_minutes: int = 10, source_region: Optional[str] = None) -> ApiResponse:
|
|
return ApiResponse(data=get_debug_event_overview(window_minutes=window_minutes, source_region=source_region))
|
|
|
|
|
|
@router.get("/runtime/debug-diagnosis", response_model=ApiResponse)
|
|
def runtime_debug_diagnosis(window_minutes: int = 10, source_region: Optional[str] = None) -> ApiResponse:
|
|
sync_summary = get_sync_summary()
|
|
return ApiResponse(data=get_debug_diagnosis(window_minutes=window_minutes, source_region=source_region, sync_summary=sync_summary))
|
|
|
|
|
|
@router.get("/runtime/debug-handoff", response_model=ApiResponse)
|
|
def runtime_debug_handoff(window_minutes: int = 10, source_region: Optional[str] = None) -> ApiResponse:
|
|
sync_summary = get_sync_summary()
|
|
runtime_status_payload = get_runtime_status()
|
|
return ApiResponse(
|
|
data=get_debug_handoff_report(
|
|
window_minutes=window_minutes,
|
|
source_region=source_region,
|
|
sync_summary=sync_summary,
|
|
readiness=runtime_status_payload.get("readiness") or {},
|
|
)
|
|
)
|
|
|
|
|
|
@router.get("/runtime/queue-health", response_model=ApiResponse)
|
|
def runtime_queue_health(window_minutes: int = 15) -> ApiResponse:
|
|
return ApiResponse(data=get_detect_queue_health(window_minutes=window_minutes))
|
|
|
|
|
|
@router.get("/runtime/health-handover", response_model=ApiResponse)
|
|
def runtime_health_handover(
|
|
node_code: Optional[str] = None,
|
|
window_minutes: int = 10,
|
|
source_region: Optional[str] = None,
|
|
) -> ApiResponse:
|
|
sync_summary = get_sync_summary()
|
|
runtime_status_payload = get_runtime_status()
|
|
data = get_debug_handoff_report(
|
|
window_minutes=window_minutes,
|
|
source_region=source_region,
|
|
sync_summary=sync_summary,
|
|
readiness=runtime_status_payload.get("readiness") or {},
|
|
)
|
|
normalized_node_code = str(node_code or "").strip()
|
|
if normalized_node_code:
|
|
data = dict(data)
|
|
data["nodes"] = [
|
|
item
|
|
for item in list(data.get("nodes") or [])
|
|
if str(item.get("node_code") or "").strip() == normalized_node_code
|
|
]
|
|
return ApiResponse(data=data)
|
|
|
|
|
|
@router.post("/runtime/sync-ingest", response_model=ApiResponse)
|
|
def runtime_sync_ingest(payload: dict, x_domaincheck_sync_token: Optional[str] = Header(default=None)) -> ApiResponse:
|
|
ok, message, data = ingest_runtime_projection(payload, shared_token=x_domaincheck_sync_token)
|
|
return ApiResponse(code=0 if ok else 1, message=message, data=data)
|
|
|
|
|
|
@router.get("/runtime/task-export", response_model=ApiResponse)
|
|
def runtime_task_export(limit: int = 1000, x_domaincheck_sync_token: Optional[str] = Header(default=None)) -> ApiResponse:
|
|
ok, message, data = export_detect_task_projection(limit=limit, shared_token=x_domaincheck_sync_token)
|
|
return ApiResponse(code=0 if ok else 1, message=message, data=data)
|
|
|
|
|
|
@router.post("/runtime/task-ack", response_model=ApiResponse)
|
|
def runtime_task_ack(payload: dict, x_domaincheck_sync_token: Optional[str] = Header(default=None)) -> ApiResponse:
|
|
ok, message, data = ack_detect_task_projection(payload, shared_token=x_domaincheck_sync_token)
|
|
return ApiResponse(code=0 if ok else 1, message=message, data=data)
|
|
|
|
|
|
@router.post("/runtime/debug-ingest", response_model=ApiResponse)
|
|
def runtime_debug_ingest(payload: dict, x_domaincheck_sync_token: Optional[str] = Header(default=None)) -> ApiResponse:
|
|
ok, message, data = ingest_debug_event(payload, shared_token=x_domaincheck_sync_token)
|
|
return ApiResponse(code=0 if ok else 1, message=message, data=data)
|
|
|
|
|
|
@router.post("/runtime/actions/{action}", response_model=ApiResponse)
|
|
def runtime_action_trigger(action: str, payload: Optional[dict] = Body(default=None)) -> ApiResponse:
|
|
ok, message, data = runtime_action(action, payload=payload)
|
|
return ApiResponse(code=0 if ok else 1, message=message, data=data)
|