//! 指令响应处理协程 //! //! 从 Redis LIST `device:reply:{imei}` 读取设备指令响应, //! 匹配 msg_id 并通过 oneshot channel 通知等待中的 HTTP 请求。 use redis::aio::ConnectionManager; use crate::commands::PendingCommands; /// 启动指令响应处理协程 /// /// 使用 BRPOP 阻塞等待所有 `device:reply:*` 队列的响应消息。 pub async fn start(redis: ConnectionManager, pending: PendingCommands) { tracing::info!("[reply_worker] 启动"); loop { let mut conn = redis.clone(); let result: Result<(String, String), redis::RedisError> = redis::cmd("BRPOP") .arg("device:replies") .arg(0) .query_async(&mut conn) .await; match result { Ok((_key, reply_json)) => { // 解析 msg_id if let Ok(reply) = serde_json::from_str::(&reply_json) { let msg_id = reply["msg_id"].as_u64().unwrap_or(0) as u32; let pending = pending.clone(); tokio::spawn(async move { if let Some(tx) = pending.remove(msg_id).await { let _ = tx.send(reply); tracing::debug!("[reply_worker] msg_id={} 已匹配", msg_id); } else { tracing::debug!("[reply_worker] msg_id={} 无等待者(可能已超时)", msg_id); } }); } } Err(e) => { tracing::error!("[reply_worker] BRPOP 错误: {}", e); tokio::time::sleep(std::time::Duration::from_secs(1)).await; } } } }