Split WebCRT and API startup; default collectors to worker process.

Extract channel/session modules and CLI guard, move UME sidebands out of main, and default NETX_RUN_INLINE_SCHEDULERS off so ops run python -m netx_api.worker.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-02 16:50:52 +08:00
parent 57b3faf9fb
commit 136f40cdae
16 changed files with 2269 additions and 2150 deletions

View file

@ -2,13 +2,16 @@
from __future__ import annotations
import time
from typing import Any
from fastapi import APIRouter, Depends
from sqlalchemy import text as sql_text
from sqlalchemy.orm import Session
from .config import settings
from .db import get_db
from .oclaw_alarm_forwarder import forwarder_status
router = APIRouter(tags=["health"])
@ -21,9 +24,87 @@ def health_live() -> dict[str, str]:
@router.get("/health/ready", status_code=200)
def health_ready(db: Session = Depends(get_db)) -> dict[str, Any]:
"""Readiness — verifies database connectivity."""
"""Readiness — DB plus scheduler deployment hint."""
out: dict[str, Any] = {"status": "ok", "probe": "ready"}
try:
db.execute(sql_text("select 1"))
return {"status": "ok", "probe": "ready", "db": "up"}
out["db"] = "up"
except Exception as exc:
return {"status": "down", "probe": "ready", "db": "down", "error": str(exc)[:240]}
return {
"status": "down",
"probe": "ready",
"db": "down",
"error": str(exc)[:240],
}
inline = bool(getattr(settings, "run_inline_schedulers", False))
out["schedulers"] = {
"inline": inline,
"mode": "inline" if inline else "external_worker",
"hint": None
if inline
else "run `python -m netx_api.worker` for config_sync / lldp_collect / port_traffic",
}
return out
@router.get("/v1/integrations/status")
def integrations_status(db: Session = Depends(get_db)) -> dict:
"""netx API + DB + oclaw bridge status."""
netx_api = {"status": "up"}
db_status: dict = {"status": "unknown"}
try:
t0 = time.monotonic()
db.execute(sql_text("select 1"))
db_status = {"status": "up", "latency_ms": int((time.monotonic() - t0) * 1000)}
except Exception as exc:
db_status = {"status": "down", "error": str(exc)[:240]}
oclaw_status: dict = {"status": "unknown"}
fwd = forwarder_status()
if not bool(fwd.get("enabled")):
oclaw_status = {
"status": "unknown",
"mode": "ws",
"enabled": False,
"connected": False,
"error_kind": "disabled",
"error": "NETX_OCLAW_ALARM_WS_ENABLED=false or missing token/url",
"forwarder": fwd,
}
elif bool(fwd.get("paused")):
oclaw_status = {
"status": "unknown",
"mode": "ws",
"enabled": True,
"connected": False,
"error_kind": "paused",
"error": "oclaw_alarm_forwarder runtime task paused",
"forwarder": fwd,
}
elif bool(fwd.get("connected")):
oclaw_status = {
"status": "up",
"mode": "ws",
"enabled": True,
"connected": True,
"queue_size": int(fwd.get("queue_size") or 0),
"published_ok": int(fwd.get("published_ok") or 0),
"published_fail": int(fwd.get("published_fail") or 0),
"url": str(fwd.get("url") or ""),
"forwarder": fwd,
}
else:
oclaw_status = {
"status": "down",
"mode": "ws",
"enabled": True,
"connected": False,
"error_kind": "ws_disconnected",
"error": "oclaw netx-bridge WebSocket not connected",
"queue_size": int(fwd.get("queue_size") or 0),
"url": str(fwd.get("url") or ""),
"forwarder": fwd,
}
return {"netx_api": netx_api, "db": db_status, "oclaw_bridge": oclaw_status}