Files
2026-07-13 13:32:32 +08:00

91 lines
2.8 KiB
Python

"""Admin API — 管理操作(迁移、诊断、配置)。"""
import json
import logging
from pathlib import Path
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import text
from ..db import get_db
from ..services.event_bus import get_event_bus
log = logging.getLogger("edict.api.admin")
router = APIRouter()
@router.get("/health/deep")
async def deep_health(db: AsyncSession = Depends(get_db)):
"""深度健康检查:Postgres + Redis 连通性。"""
checks = {"postgres": False, "redis": False}
# Postgres
try:
result = await db.execute(text("SELECT 1"))
checks["postgres"] = result.scalar() == 1
except Exception as e:
checks["postgres_error"] = str(e)
# Redis
try:
bus = await get_event_bus()
pong = await bus.redis.ping()
checks["redis"] = pong is True
except Exception as e:
checks["redis_error"] = str(e)
status = "ok" if all(checks.get(k) for k in ["postgres", "redis"]) else "degraded"
return {"status": status, "checks": checks}
@router.get("/pending-events")
async def pending_events(
topic: str = "task.dispatch",
group: str = "dispatcher",
count: int = 20,
):
"""查看未 ACK 的 pending 事件(诊断工具)。"""
bus = await get_event_bus()
pending = await bus.get_pending(topic, group, count)
return {
"topic": topic,
"group": group,
"pending": [
{
"entry_id": str(p.get("message_id", "")),
"consumer": str(p.get("consumer", "")),
"idle_ms": p.get("time_since_delivered", 0),
"delivery_count": p.get("times_delivered", 0),
}
for p in pending
] if pending else [],
}
@router.post("/migrate/check")
async def migration_check():
"""检查旧数据文件是否存在。"""
data_dir = Path(__file__).parents[4] / "data"
files = {
"tasks_source": (data_dir / "tasks_source.json").exists(),
"live_status": (data_dir / "live_status.json").exists(),
"agent_config": (data_dir / "agent_config.json").exists(),
"officials_stats": (data_dir / "officials_stats.json").exists(),
}
return {"data_dir": str(data_dir), "files": files}
@router.get("/config")
async def get_config():
"""获取当前运行配置(脱敏)。"""
from ..config import get_settings
settings = get_settings()
return {
"port": settings.port,
"debug": settings.debug,
"database": settings.database_url.split("@")[-1] if "@" in settings.database_url else "***",
"redis": settings.redis_url.split("@")[-1] if "@" in settings.redis_url else settings.redis_url,
"scheduler_scan_interval": settings.scheduler_scan_interval_seconds,
}