You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.2 KiB
7.2 KiB
WebSocket第二次连接事件推送问题修复方案
问题描述
WebSocket第一次连接后能正常推送数据,但第二次连接时需要等待 adb 设备接入或重启后才能推送数据。
问题根因分析
1. 事件缓冲队列被清空
在 app/core/device/event_manager.py 的 _get_events_and_clients() 方法中,第218行的 self._event_buffer.clear() 会在第一次推送后完全清空事件缓冲队列。
2. 设备监控机制是事件驱动的
系统使用 track_devices() 方法监控设备状态变化,只有当设备状态发生变化时才会触发事件。当执行 adb reboot 时:
- 设备断开:触发
device_disconnected事件 - 设备重连:触发
device_connected事件 - 新事件填充缓冲队列,WebSocket客户端就能获取到数据
3. 缺乏主动设备状态检查
当前设计是被动监控模式,只监听设备状态变化事件,不会主动查询当前已连接的设备。
修复方案
方案选择:在WebSocket客户端连接时主动检查设备状态
优势:
- 即时响应:客户端连接后立即能获取到当前设备状态
- 最小改动:只需要在连接逻辑中添加一个方法调用
- 性能友好:只在需要时检查,不会持续消耗资源
- 用户体验好:解决了第二次连接需要等待的问题
实现策略
- 保持原有逻辑不变:不修改现有的设备监控机制
- 异步执行:不阻塞API响应
- 安全处理:完整的错误处理和日志记录
- 避免重复:只处理自动发现的设备,避免重复处理已注册设备
具体实现
1. 修改 WebSocketManager.connect_client() 方法
在现有的异步任务中添加设备状态检查:
async def connect_client(self, name: str) -> bool:
"""连接指定客户端"""
try:
# ... 现有连接逻辑保持不变 ...
# 新增:异步注册设备事件推送(不阻塞API响应)
logger.debug(f"为客户端 {name} 异步注册设备事件推送")
device_manager = await self._get_device_manager()
# 创建异步任务并添加错误处理
register_task = asyncio.create_task(self._async_register_device_events(name, device_manager))
register_task.add_done_callback(lambda t: self._handle_async_task_result(t, f"注册设备事件推送-{name}"))
# 新增:异步推送缓冲的事件到新连接的客户端(不阻塞API响应)
logger.debug(f"为客户端 {name} 异步推送缓冲事件")
push_task = asyncio.create_task(self._async_push_buffered_events(name, device_manager))
push_task.add_done_callback(lambda t: self._handle_async_task_result(t, f"推送缓冲事件-{name}"))
# 新增:异步检查当前设备状态(不阻塞API响应)
logger.debug(f"为客户端 {name} 异步检查当前设备状态")
check_task = asyncio.create_task(self._async_check_current_device_status(name, device_manager))
check_task.add_done_callback(lambda t: self._handle_async_task_result(t, f"检查设备状态-{name}"))
logger.info(f"WebSocket管理器客户端连接成功: {name}")
return True
except Exception as e:
logger.error(f"WebSocket管理器连接客户端失败: {name} - {e}")
return False
2. 添加异步设备状态检查方法
async def _async_check_current_device_status(self, client_name: str, device_manager):
"""异步检查当前设备状态(不阻塞API响应)"""
try:
logger.debug(f"开始为客户端 {client_name} 检查当前设备状态")
# 获取当前所有设备
all_devices = await device_manager.get_all_devices_unified()
logger.debug(f"当前系统中有 {len(all_devices)} 个设备")
# 检查是否有在线设备需要生成事件
online_devices = [d for d in all_devices if d.get("status") == "device"]
if not online_devices:
logger.debug(f"当前没有在线设备,无需生成事件")
return
# 为每个在线设备生成连接事件(如果还没有的话)
for device in online_devices:
device_id = device["device_id"]
device_source = device.get("source", "unknown")
# 只处理自动发现的设备,避免重复处理已注册设备
if device_source == "auto_discovered":
logger.debug(f"为在线设备生成连接事件: {device_id}")
await device_manager.handle_auto_discovered_device_event(
device_id=device_id,
status="device",
device_info=device.get("device_info", {})
)
else:
logger.debug(f"跳过已注册设备: {device_id}")
logger.info(f"为客户端 {client_name} 设备状态检查完成,处理了 {len(online_devices)} 个在线设备")
except Exception as e:
logger.error(f"为客户端 {client_name} 检查设备状态失败: {e}")
修复效果
修复前
- 第一次连接:能正常推送数据(有历史事件)
- 第二次连接:需要等待 adb 设备接入或重启才能推送数据(缓冲队列被清空)
- adb reboot:能激活推送(生成新事件)
修复后
- 第一次连接:正常推送历史事件 + 当前设备状态
- 第二次连接:正常推送历史事件 + 当前设备状态(无需等待adb重启)
- 设备状态变化:原有的自动监听机制继续工作
- 向后兼容:完全保持原有功能不变
安全性保证
1. 完全不影响原有逻辑
- ✅ 保持原有的异步任务结构
- ✅ 不改变现有的设备监控机制
- ✅ 不修改
handle_auto_discovered_device_event方法 - ✅ 保持原有的错误处理机制
2. 保证自动监听不失效
- ✅ 原有的
track_devices()监控继续工作 - ✅ 设备状态变化仍然会触发事件
- ✅ 只是额外添加了主动检查,不会替代原有机制
- ✅ 两个机制并行工作,互不干扰
3. 性能友好
- ✅ 异步执行,不阻塞API响应
- ✅ 只在客户端连接时执行一次
- ✅ 不会持续消耗资源
- ✅ 不影响原有的监控性能
测试建议
- 第一次WebSocket连接测试:验证能正常推送数据
- 第二次WebSocket连接测试:验证无需等待adb重启即可推送数据
- 设备状态变化测试:验证原有的自动监听机制仍然正常工作
- 多次连接测试:确保修复的稳定性
- 性能测试:确保不影响系统性能
文件修改清单
app/core/websocket/manager.py:添加设备状态检查逻辑docs/modify.md:记录修改内容
风险评估
风险等级:低
原因:
- 只添加新功能,不修改现有逻辑
- 异步执行,不影响主流程
- 有完整的错误处理
- 向后兼容,不影响现有功能
实施计划
- 第一步:生成修复方案文档(已完成)
- 第二步:实施代码修复
- 第三步:测试验证
- 第四步:更新修改记录
创建时间: 2025-01-27
创建人: AI Assistant
状态: 待实施