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

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客户端连接时主动检查设备状态

优势:

  • 即时响应:客户端连接后立即能获取到当前设备状态
  • 最小改动:只需要在连接逻辑中添加一个方法调用
  • 性能友好:只在需要时检查,不会持续消耗资源
  • 用户体验好:解决了第二次连接需要等待的问题

实现策略

  1. 保持原有逻辑不变:不修改现有的设备监控机制
  2. 异步执行:不阻塞API响应
  3. 安全处理:完整的错误处理和日志记录
  4. 避免重复:只处理自动发现的设备,避免重复处理已注册设备

具体实现

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}")

修复效果

修复前

  1. 第一次连接:能正常推送数据(有历史事件)
  2. 第二次连接:需要等待 adb 设备接入或重启才能推送数据(缓冲队列被清空)
  3. adb reboot:能激活推送(生成新事件)

修复后

  1. 第一次连接:正常推送历史事件 + 当前设备状态
  2. 第二次连接:正常推送历史事件 + 当前设备状态(无需等待adb重启)
  3. 设备状态变化:原有的自动监听机制继续工作
  4. 向后兼容:完全保持原有功能不变

安全性保证

1. 完全不影响原有逻辑

  • 保持原有的异步任务结构
  • 不改变现有的设备监控机制
  • 不修改 handle_auto_discovered_device_event 方法
  • 保持原有的错误处理机制

2. 保证自动监听不失效

  • 原有的 track_devices() 监控继续工作
  • 设备状态变化仍然会触发事件
  • 只是额外添加了主动检查,不会替代原有机制
  • 两个机制并行工作,互不干扰

3. 性能友好

  • 异步执行,不阻塞API响应
  • 只在客户端连接时执行一次
  • 不会持续消耗资源
  • 不影响原有的监控性能

测试建议

  1. 第一次WebSocket连接测试:验证能正常推送数据
  2. 第二次WebSocket连接测试:验证无需等待adb重启即可推送数据
  3. 设备状态变化测试:验证原有的自动监听机制仍然正常工作
  4. 多次连接测试:确保修复的稳定性
  5. 性能测试:确保不影响系统性能

文件修改清单

  • app/core/websocket/manager.py:添加设备状态检查逻辑
  • docs/modify.md:记录修改内容

风险评估

风险等级:低

原因:

  1. 只添加新功能,不修改现有逻辑
  2. 异步执行,不影响主流程
  3. 有完整的错误处理
  4. 向后兼容,不影响现有功能

实施计划

  1. 第一步:生成修复方案文档(已完成)
  2. 第二步:实施代码修复
  3. 第三步:测试验证
  4. 第四步:更新修改记录

创建时间: 2025-01-27
创建人: AI Assistant
状态: 待实施