This commit is contained in:
2025-10-17 20:56:50 +08:00
commit 90094ccd5a
342 changed files with 144988 additions and 0 deletions

View File

@@ -0,0 +1,342 @@
# 问题修复:批量发车超时 - 使用统一通信机制 v3.9.7
## 🚀 概述
**问题**
- ✅ 游戏功能模块单独测试:**成功且非常快**
- ❌ 批量自动化测试:**超时20秒**
**用户反馈**
> "单独测试是成功的,而且查询的非常快"
**根本原因**
- 批量自动化和游戏功能模块使用了**不同的通信机制**
- 批量自动化复用 `client` 对象,在等待和执行期间 `client` 可能失效
- 导致后续命令的 Promise 永远不会被 resolve
---
## 🔍 问题分析
### 之前的实现v3.9.6及之前)
#### 游戏功能模块(成功✅)
```javascript
// CarManagement.vue
const response = await tokenStore.sendMessageAsync(
tokenId,
'car_getrolecar',
{},
10000
)
```
**特点**
- ✅ 每次发送时获取最新的 `client`
- ✅ 使用响应式连接对象 `wsConnections.value[tokenId]`
- ✅ 简单可靠
---
#### 批量自动化(失败❌)
```javascript
// batchTaskStore.js (v3.9.6)
const client = await ensureConnection(tokenId) // 获取一次
await new Promise(resolve => setTimeout(resolve, 2000)) // 等待2秒
// 后续多次使用这个 client
await client.sendWithPromise('car_getrolecar', {}, 20000) // ❌ 可能失效
await client.sendWithPromise('car_refresh', { carId }, 5000) // ❌ 可能失效
await client.sendWithPromise('car_claim', { carId }, 5000) // ❌ 可能失效
await client.sendWithPromise('car_send', { carId }, 5000) // ❌ 可能失效
```
**问题**
- ❌ 一次性获取 `client` 后长时间复用
- ❌ 在等待期间2秒和执行期间`client` 可能失效
- ❌ 使用非响应式连接对象 `tokenStore.wsConnections[tokenId]`
---
### 为什么 client 会失效?
#### 原因1等待期间连接被替换
```javascript
// 时间点 T0: 获取 client
const client = await ensureConnection(tokenId)
// 时间点 T0 → T2: 等待2秒
await new Promise(resolve => setTimeout(resolve, 2000))
// 时间点 T2: client 可能已经失效
// - 连接可能被重置
// - tokenStore.reconnectWebSocket 可能创建了新的 client
// - 旧的 client 引用失效
await client.sendWithPromise('car_getrolecar', {}, 20000) // ❌ 超时
```
#### 原因2Promise 管理器状态不一致
- WebSocket client 内部有 Promise 管理器
- 如果连接重置Promise 管理器也会重置
- 旧的 Promise 永远不会被 resolve
#### 原因3事件监听器失效
- WebSocket client 依赖 `onmessage` 事件
- 连接重置后,旧的事件监听器失效
- 新消息不会触发旧 client 的 Promise resolve
---
## 🛠️ 解决方案 v3.9.7
### 核心改进:统一使用 `tokenStore.sendMessageAsync`
**不再复用 `client` 对象,每次发送时都获取最新的 `client`**
---
### 修改详情
#### 修改1查询车辆第1152行
```diff
- const queryResponse = await client.sendWithPromise('car_getrolecar', {}, 20000)
+ const queryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
```
#### 修改2刷新车辆第1200行
```diff
- await client.sendWithPromise('car_refresh', { carId: carId }, 5000)
+ await tokenStore.sendMessageAsync(tokenId, 'car_refresh', { carId: carId }, 5000)
```
#### 修改3刷新后重新查询第1227行
```diff
- const reQueryResponse = await client.sendWithPromise('car_getrolecar', {}, 20000)
+ const reQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
```
#### 修改4收获车辆第1268行
```diff
- await client.sendWithPromise('car_claim', { carId: carId }, 5000)
+ await tokenStore.sendMessageAsync(tokenId, 'car_claim', { carId: carId }, 5000)
```
#### 修改5发送前最后查询第1298行
```diff
- const finalQueryResponse = await client.sendWithPromise('car_getrolecar', {}, 20000)
+ const finalQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
```
#### 修改6发送车辆第1311行
```diff
- await client.sendWithPromise('car_send', { carId, helperId: 0, text: "" }, 5000)
+ await tokenStore.sendMessageAsync(tokenId, 'car_send', { carId, helperId: 0, text: "" }, 5000)
```
---
## ✅ 优势
### 1. 统一通信机制
- ✅ 批量自动化与游戏功能模块使用**相同的通信机制**
- ✅ 代码一致性和可维护性大幅提升
### 2. 每次获取最新 client
- ✅ 每次发送命令时都通过 `wsConnections.value[tokenId]` 获取最新的 `client`
- ✅ 避免 `client` 对象失效问题
### 3. 使用响应式状态
-`wsConnections.value[tokenId]` 是响应式的
- ✅ 总是获取到最新的连接状态
### 4. 简单可靠
- ✅ 逻辑更简单清晰
- ✅ 与游戏功能模块保持一致
- ✅ 避免复杂的 client 管理
---
## 📊 预期效果
### v3.9.6(修改前)
```
✅ WebSocket连接成功
⏳ 等待连接稳定... (2秒)
📤 发送消息: car_getrolecar {}
💓 心跳消息... (不断收发)
❌ 20秒后超时没有收到 car_getrolecarresp
```
**问题**client 对象在等待期间失效
---
### v3.9.7(修改后)
```
✅ WebSocket连接成功
⏳ 等待连接稳定... (2秒)
📤 发送消息: car_getrolecar {}
✅ 收到响应: car_getrolecarresp (1-2秒内) ← 预期快速成功
✅ [token_xxx] 查询到 4 辆车
```
**改进**:每次发送都获取最新的 client避免失效
---
## 🧪 验证步骤
### 1. 重启开发服务器
```bash
# 在项目根目录
npm run dev
```
### 2. 批量测试
1. 打开批量自动化面板
2. 选择**2个账号**第2个账号待发车状态
3. 只勾选**"发车"**任务
4. 点击"开始执行"
### 3. 观察结果
#### 期望结果(成功✅)
```
🎯 开始执行 Token: 805服-0-xxx
✅ WebSocket连接成功
⏳ 等待连接稳定...
📌 执行任务 [1/1]: sendCar
🚗 [token_xxx] 开始查询俱乐部车辆...
✅ [token_xxx] 查询到 4 辆车 ← 应该1-2秒内完成
🔄 [token_xxx] 开始批量刷新车辆...
✅ [token_xxx] 刷新车辆成功: carId
🎁 [token_xxx] 开始批量收获...
✅ [token_xxx] 收获车辆成功: carId
🚀 [token_xxx] 开始批量发送...
✅ [token_xxx] 发送车辆成功: carId
✅ Token完成: 805服-0-xxx
⏳ Token token_xxx 将在 3.0秒 后建立连接 ← 串行执行
🎯 开始执行 Token: 805服-1-xxx
✅ WebSocket连接成功
⏳ 等待连接稳定...
📌 执行任务 [1/1]: sendCar
🚗 [token_xxx] 开始查询俱乐部车辆...
✅ [token_xxx] 查询到 4 辆车 ← 应该1-2秒内完成
✅ Token完成: 805服-1-xxx
📊 统计信息: {total: 2, success: 2, failed: 0} ✅
```
**关键指标**
- ✅ 查询车辆应该在1-2秒内完成而不是20秒超时
- ✅ 每个步骤都能快速响应
- ✅ 整体流程顺畅
---
#### 如果仍然失败unlikely
如果修改后仍然超时,说明问题更深层:
1. 可能是服务器端限制
2. 可能需要增加账号间隔5-10秒
3. 可能需要检查网络环境
但根据分析,**v3.9.7应该能解决问题** ✅
---
## 📝 文件修改清单
### 修改文件
1.`src/stores/batchTaskStore.js`
- 第1152行查询车辆
- 第1200行刷新车辆
- 第1227行刷新后重新查询
- 第1268行收获车辆
- 第1298行发送前最后查询
- 第1311行发送车辆
### 新增文档
1.`MD说明/批量自动化发车流程分析v3.9.6.md` - 流程分析文档
2.`MD说明/问题修复-批量发车超时使用统一通信机制v3.9.7.md` - 本文档
---
## 🔄 版本信息
- **版本号**v3.9.7
- **修复日期**2025-10-08
- **影响范围**:批量自动化 - 发车任务
- **向后兼容**:✅ 完全兼容
- **破坏性变更**:❌ 无
---
## 💡 技术要点
### tokenStore.sendMessageAsync 内部实现
```javascript
// src/stores/tokenStore.js 第1414-1430行
const sendMessageWithPromise = async (tokenId, cmd, params = {}, timeout = 1000) => {
// 1. 获取最新的连接对象(响应式)
const connection = wsConnections.value[tokenId]
// 2. 检查连接状态
if (!connection || connection.status !== 'connected') {
return Promise.reject(new Error(`WebSocket未连接 [${tokenId}]`))
}
// 3. 获取最新的 client
const client = connection.client
if (!client) {
return Promise.reject(new Error(`WebSocket客户端不存在 [${tokenId}]`))
}
// 4. 发送命令
try {
return await client.sendWithPromise(cmd, params, timeout)
} catch (error) {
return Promise.reject(error)
}
}
```
**关键优势**
- ✅ 每次调用都重新获取 `connection``client`
- ✅ 使用 `wsConnections.value`(响应式)
- ✅ 检查 `connection.status === 'connected'`
- ✅ 确保 `client` 总是最新的
---
## 🎯 总结
### 问题本质
- **批量自动化复用 `client` 对象**
- **在等待和执行期间,`client` 可能失效**
- **导致命令的 Promise 永远不会被 resolve**
### 解决方案
- **统一使用 `tokenStore.sendMessageAsync`**
- **每次发送都获取最新的 `client`**
- **与游戏功能模块保持一致**
### 预期结果
- ✅ 批量发车应该和单独测试一样**快速成功**
- ✅ 查询车辆应该在1-2秒内完成
- ✅ 整体流程顺畅可靠
---
## 🚀 下一步
1. **重启开发服务器**
2. **批量测试2个账号**
3. **观察是否快速成功**
4. **享受批量发车的便利!** 🎉
如果测试成功,说明问题已完美解决! ✅