2026-07-02 05:38:01 +08:00

71 lines
2.0 KiB
Rust

//! 设备服务节点管理 API
//!
//! 设备服务启动时注册到 API 服务,定期发送心跳。
//! API 服务通过节点健康状况判断设备服务是否在线。
use axum::extract::{Path, State};
use axum::Json;
use serde::Deserialize;
use serde_json::{json, Value};
use crate::commands::AppState;
use crate::error::AppError;
/// 节点注册请求体
#[derive(Debug, Deserialize)]
pub struct NodeRegisterRequest {
pub node_id: String,
pub ip: String,
pub tcp_port: u16,
}
/// POST /api/nodes/register — 设备服务注册
pub async fn register_node(
State(state): State<AppState>,
Json(req): Json<NodeRegisterRequest>,
) -> Result<Json<Value>, AppError> {
state.nodes.register(&req.node_id, &req.ip, req.tcp_port).await;
tracing::info!("[节点注册] node_id={}", req.node_id);
Ok(Json(json!({"suc": 1})))
}
/// POST /api/nodes/:node_id/heartbeat — 节点心跳
pub async fn node_heartbeat(
State(state): State<AppState>,
Path(node_id): Path<String>,
) -> Result<Json<Value>, AppError> {
if state.nodes.heartbeat(&node_id).await {
Ok(Json(json!({"suc": 1})))
} else {
Ok(Json(json!({"suc": 0, "err": "节点未注册"})))
}
}
/// POST /api/nodes/:node_id/deregister — 节点注销
pub async fn deregister_node(
State(state): State<AppState>,
Path(node_id): Path<String>,
) -> Result<Json<Value>, AppError> {
state.nodes.remove(&node_id).await;
tracing::info!("[节点注销] node_id={}", node_id);
Ok(Json(json!({"suc": 1})))
}
/// GET /api/nodes — 节点列表
pub async fn list_nodes(
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
let nodes = state.nodes.list().await;
let list: Vec<Value> = nodes
.into_iter()
.map(|n| {
json!({
"node_id": n.node_id,
"ip": n.ip,
"tcp_port": n.tcp_port,
})
})
.collect();
Ok(Json(json!({"nodes": list, "count": list.len()})))
}