# 任务017:重构审查问题修复 ## 目标 修复TCP服务重构审查发现的P0/P1问题。 ## 修复清单 ### P0:Redis类型冲突 **位置:** `device-server/src/main.rs` **问题:** `register_node`用`SET`(string类型),`heartbeat`用`HSET`(hash类型),同一key操作触发`WRONGTYPE`错误。 **修复:** 统一用HSET: ```rust // 节点注册 async fn register_node(redis: &Redis, node_id: &str, ip: &str, tcp_port: u16) { redis.hset(&format!("node:{}", node_id), &[ ("ip", ip), ("tcp_port", &tcp_port.to_string()), ("status", "online"), ("last_heartbeat", &Instant::now().elapsed().as_secs().to_string()), ]).await; redis.expire(&format!("node:{}", node_id), 300).await; } // 节点心跳 async fn heartbeat(redis: &Redis, node_id: &str) { redis.hset(&format!("node:{}", node_id), &[ ("last_heartbeat", &Instant::now().elapsed().as_secs().to_string()), ]).await; redis.expire(&format!("node:{}", node_id), 300).await; } ``` ### P1:节点管理双轨制 **问题:** API服务维护内存`NodeRegistry`,设备服务直接写Redis,两者不关联。 **修复方案A(推荐):** API服务从Redis读取节点信息 ```rust // API服务节点列表 async fn list_nodes(redis: &Redis) -> Result>> { let keys = redis.keys("node:*").await?; let mut nodes = Vec::new(); for key in keys { let node_id = key.strip_prefix("node:").unwrap(); let info: HashMap = redis.hgetall(&key).await?; nodes.push(NodeInfo { id: node_id.to_string(), ip: info.get("ip").cloned().unwrap_or_default(), tcp_port: info.get("tcp_port").and_then(|p| p.parse().ok()).unwrap_or(0), status: info.get("status").cloned().unwrap_or_default(), last_heartbeat: info.get("last_heartbeat").cloned().unwrap_or_default(), }); } Ok(Json(nodes)) } ``` **修复方案B:** 设备服务通过HTTP注册到API服务 - 设备服务启动时POST到`/api/nodes/register` - API服务存内存 - 心跳POST到`/api/nodes/:id/heartbeat` - 注销POST到`/api/nodes/:id/deregister` ### P2:配置系统 **问题:** 代码用`dotenvy`读环境变量,config.toml形同虚设。 **修复:** 二选一 - 方案A:用`toml` crate读config.toml - 方案B:删除config.toml,只用.env ### P3:协议结构体重复 **问题:** `DeviceMessage`等结构体在两个服务中重复定义。 **修复:** 暂不处理,后续提取shared crate时统一。 ### P4:限流器同步Mutex **问题:** 限流器用`std::sync::Mutex`,不符合异步规范。 **修复:** 改用`tokio::sync::Mutex`或`RwLock`。 ## 质量约束 1. 完成代码后执行 `cargo check` + `cargo clippy`,零报错零警告 2. 分层拆分,单函数≤80行,命名语义化,完整注释 3. 所有外部IO/网络请求异常捕获,禁止裸panic 4. 分支逻辑全覆盖,不遗漏兜底分支 5. 常量抽离,不使用废弃API 6. Rust内存安全,合理管理所有权,禁用unsafe无合理理由