Files
jdy_fastapi/BUG_REPORT.md
T
2025-11-07 17:48:49 +08:00

507 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Bug 报告
## 严重程度说明
- 🔴 **严重**: 可能导致程序崩溃或数据丢失
- 🟡 **中等**: 可能导致功能异常或错误处理不当
- 🟢 **轻微**: 代码质量问题,不影响功能但需要改进
---
## 1. api.py (根目录) - 错误日志键名错误
### 位置
- 第540行:`entry_data_batch_delete` 方法
- 第654行:`workflow_task_hand_over` 方法
- 第701行:`get_upload_token` 方法
- 第745行:`upload_file` 方法
### 问题描述
🟡 **中等** - 在错误日志中使用了错误的键名 `data['data_list']`,但这些方法中可能不存在该键。
### 代码示例
```python
# 第540行 - entry_data_batch_delete
error_task_logger.error(
f"任务 {data['data_list'][start_index:end_index]} 连续{max_retries}次请求失败,放弃此次请求。")
# 应该是 data['data_ids']
# 第654行 - workflow_task_hand_over
error_task_logger.error(
f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。")
# 该方法没有 data_list 键
# 第701行 - get_upload_token
error_task_logger.error(
f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。")
# 该方法没有 data_list 键
# 第745行 - upload_file
error_task_logger.error(
f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。")
# 该方法没有 data_list 键
```
### 修复建议
使用正确的键名或使用 `data.get()` 方法安全访问。
---
## 2. main.py - Handler 调用问题
### 位置
第76行和第80行
### 问题描述
🟡 **中等** - 当 `action_map.get()` 返回默认的 lambda 函数时,handler 是一个函数对象,但代码中直接将其传递给 `enqueue_task`,这应该是正确的。但如果 handler 是 lambda,需要确保它能被正确调用。
### 代码示例
```python
# 第76行
handler = action_map.get(sub_action, lambda x: {'msg': '未执行'})
# 第80行
handler = action_map.get(action, lambda x: {'msg': '未知的操作'})
```
### 修复建议
确保所有 handler 都能正确处理数据参数。如果 handler 可能返回 None,需要添加检查。
---
## 3. main.py - 队列阻塞风险
### 位置
第86行
### 问题描述
🟡 **中等** - 使用 `response_queue.get()` 会无限期阻塞,如果任务处理线程出现问题,可能导致请求永远挂起。
### 代码示例
```python
result = await anyio.to_thread.run_sync(response_queue.get)
```
### 修复建议
添加超时机制或使用 `response_queue.get(timeout=...)`
---
## 4. app/api.py - 数组访问未检查
### 位置
第712-713行:`get_upload_token` 方法
### 问题描述
🔴 **严重** - 直接访问 `res_j['token_and_url_list'][0]` 可能导致 KeyError 或 IndexError。
### 代码示例
```python
res_j = res.json()
upload_url = res_j['token_and_url_list'][0]['url']
upload_token = res_j['token_and_url_list'][0]['token']
```
### 修复建议
添加检查:
```python
token_list = res_j.get('token_and_url_list', [])
if not token_list:
raise ValueError("未获取到上传凭证")
upload_url = token_list[0].get('url')
upload_token = token_list[0].get('token')
```
---
## 5. app/module/F6_Plugin_module.py - 数组访问未检查
### 位置
第40行:`accept_file` 方法
### 问题描述
🔴 **严重** - 直接访问 `data['data']['附件'][0]['url']` 可能导致 KeyError 或 IndexError。
### 代码示例
```python
url = data['data']['附件'][0]['url']
```
### 修复建议
添加检查:
```python
attachments = data.get('data', {}).get('附件', [])
if not attachments:
return None, data
url = attachments[0].get('url')
```
---
## 6. app/module/F6_Plugin_module.py - 键访问未检查
### 位置
第96行:`check_file` 方法
### 问题描述
🔴 **严重** - 直接访问 `data1['data']['Action(隐藏)']` 可能导致 KeyError。
### 代码示例
```python
action = data1['data']['Action(隐藏)']
```
### 修复建议
使用安全访问:
```python
action = data1.get('data', {}).get('Action(隐藏)')
if not action:
return {'msg': '缺少Action字段'}
```
---
## 7. app/module/module.py - 临时文件未清理
### 位置
第21-31行:`get_captcha` 方法
### 问题描述
🟢 **轻微** - 创建了临时文件 `captcha.png``preprocessed_captcha.png`,但没有清理。
### 代码示例
```python
with open('captcha.png', 'wb') as f:
f.write(response.content)
# ... 处理文件 ...
image.save('preprocessed_captcha.png')
```
### 修复建议
使用临时文件或处理完后删除:
```python
import tempfile
import os
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp:
tmp.write(response.content)
tmp_path = tmp.name
try:
# 处理文件
...
finally:
if os.path.exists(tmp_path):
os.remove(tmp_path)
```
---
## 8. app/module/module.py - group_id 可能为空
### 位置
第65-73行:`login_in` 方法
### 问题描述
🟡 **中等** - 如果找不到匹配的 `company_name``group_id` 为空字符串,后续请求可能失败。
### 代码示例
```python
group_id = ''
for group in res_json.get('data', []):
if group["groupName"] == company_name:
group_id = group.get("groupId")
token = quote(res_json['token'])
url = (f'https://yunxiu.f6car.cn/kzf6/user/loginAfterChooseGroup?'
f'token={token}&groupId={group_id}&macAddress=')
```
### 修复建议
添加检查:
```python
if not group_id:
logger.error(f"未找到公司名称: {company_name}")
return None
```
---
## 9. app/module/module.py - 时间判断逻辑错误
### 位置
第119行:`delete_customer_background` 方法(在 delete_tasks.py 中)
第246行:`delete_car_background` 方法(在 delete_tasks.py 中)
### 问题描述
🟡 **中等** - 时间判断逻辑错误:`if 20 <= now.hour <= 8:` 永远不会为 True(20 不可能小于等于 8)。
### 代码示例
```python
now = datetime.now()
if 20 <= now.hour <= 8:
time.sleep(1)
else:
time.sleep(3)
```
### 修复建议
应该是:
```python
now = datetime.now()
if 8 <= now.hour <= 20: # 8点到20点之间
time.sleep(3.5)
else: # 其他时间
time.sleep(1.5)
```
---
## 10. app/tasks/common.py - 数组访问未检查
### 位置
第56行:`approve_workflow` 方法
### 问题描述
🔴 **严重** - 直接访问 `json['tasks']``json['tasks'][0]` 可能导致 KeyError 或 IndexError。
### 代码示例
```python
for task in json['tasks']:
if task['status'] == 0:
username = task['assignee']['username']
instance_id = task['instance_id']
task_id = task['task_id']
```
### 修复建议
添加检查:
```python
tasks = json.get('tasks', [])
if not tasks:
logger.error("未找到待处理任务")
return
for task in tasks:
if task.get('status') == 0:
assignee = task.get('assignee', {})
username = assignee.get('username')
instance_id = task.get('instance_id')
task_id = task.get('task_id')
if username and instance_id and task_id:
break
```
---
## 11. app/tasks/delete_tasks.py - 数组访问未检查
### 位置
第62行:`delete_customer_background` 方法
第154行:`delete_car_background` 方法
### 问题描述
🔴 **严重** - 直接访问 `org_res.json().get("data").get("list")[0]` 可能导致 IndexError。
### 代码示例
```python
operate_org_id = org_res.json().get("data").get("list")[0].get("orgId")
```
### 修复建议
添加检查:
```python
org_data = org_res.json().get("data", {}).get("list", [])
if not org_data:
logger.error("未获取到门店信息")
return
operate_org_id = org_data[0].get("orgId")
```
---
## 12. app/tasks/customer_tasks.py - 重试逻辑错误
### 位置
第52-67行:`modify_customer_info_background` 方法
### 问题描述
🟡 **中等** - `retry_count` 在循环外部初始化,导致每次页面请求都使用相同的重试计数,而不是每页独立重试。
### 代码示例
```python
retry_count = 0
for page in range(1, total_pages + 1):
while retry_count < max_retries:
# ...
if response.status_code == 200:
break
else:
retry_count += 1
```
### 修复建议
`retry_count` 移到循环内部:
```python
for page in range(1, total_pages + 1):
retry_count = 0
while retry_count < max_retries:
# ...
```
---
## 13. app/tasks/delete_tasks.py - 条件判断错误
### 位置
第115-116行:`delete_customer_background` 方法
### 问题描述
🟡 **中等** - `if success + fail < len(json_data):` 这个条件判断逻辑有问题,应该检查是否还有未处理的项。
### 代码示例
```python
if success + fail < len(json_data):
continue
```
### 修复建议
这个条件判断似乎是想检查是否处理完所有项,但逻辑不正确。应该移除或修正。
---
## 14. app/tasks/delete_tasks.py - 变量作用域问题
### 位置
第215行:`delete_car_background` 方法
### 问题描述
🟡 **中等** - 在循环外部使用了 `page` 变量,但 `page` 只在循环内部定义。
### 代码示例
```python
for page in range(1, all_page + 1):
# ...
for item in items:
# ...
if not car_id or not customer_id:
logger.info(f"页码 {page} 中缺少必要的ID信息") # page 在这里可用
# ...
# ...
logger.error(f"删除失败: 页码 {page}, ...") # page 在这里可用
```
实际上这个不是bug`page` 在循环内部是可用的。但如果在循环外部使用就会有问题。
---
## 15. api.py (根目录) - 文件资源泄漏
### 位置
第721-747行:`upload_file` 方法
### 问题描述
🔴 **严重** - 文件在循环外部打开,如果循环中发生异常或提前返回,文件可能不会被关闭,导致资源泄漏。
### 代码示例
```python
f = open(file_path, 'rb')
files = {"file": f}
retries = 0
while retries <= max_retries:
try:
res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10)
# ...
if res.status_code == 200:
return data_get # 提前返回,文件未关闭!
# ...
except requests.exceptions.RequestException as e:
# 如果异常发生,文件可能不会被关闭
# ...
f.close() # 只有在循环结束后才会执行
```
### 修复建议
使用 `with` 语句确保文件总是被关闭:
```python
retries = 0
result = None
while retries <= max_retries:
try:
with open(file_path, 'rb') as f:
files = {"file": f}
res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10)
res.raise_for_status()
data_get = res.json()
if res.status_code == 200:
return data_get
retries += 1
time.sleep(3)
except requests.exceptions.RequestException as e:
logger.warning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(3)
if retries > max_retries:
error_task_logger.error(f"上传文件失败,已重试{max_retries}")
return None
```
---
## 16. api.py (根目录) - 重试时文件指针问题
### 位置
第721-747行:`upload_file` 方法
### 问题描述
🟡 **中等** - 文件在循环外部打开,重试时文件指针已经移动到文件末尾,后续重试会读取空内容。
### 代码示例
```python
f = open(file_path, 'rb')
files = {"file": f}
retries = 0
while retries <= max_retries:
res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10)
# 第一次请求后,文件指针已经移动到末尾
# 重试时会读取空内容
```
### 修复建议
每次重试时重新打开文件,或使用 `with` 语句在每次循环中打开文件。
---
## 总结
### 按严重程度分类
**严重 (🔴)** - 需要立即修复:
1. app/api.py - 数组访问未检查(get_upload_token
2. app/module/F6_Plugin_module.py - 数组访问未检查(accept_file
3. app/module/F6_Plugin_module.py - 键访问未检查(check_file
4. app/tasks/common.py - 数组访问未检查(approve_workflow
5. app/tasks/delete_tasks.py - 数组访问未检查(两处)
6. api.py (根目录) - 文件资源泄漏(upload_file
**中等 (🟡)** - 建议尽快修复:
1. api.py - 错误日志键名错误(多处)
2. api.py - 重试时文件指针问题(upload_file
3. main.py - Handler 调用和队列阻塞问题
4. app/module/module.py - group_id 可能为空
5. app/module/module.py - 时间判断逻辑错误(两处)
6. app/tasks/customer_tasks.py - 重试逻辑错误
7. app/tasks/delete_tasks.py - 条件判断错误
**轻微 (🟢)** - 代码质量改进:
1. app/module/module.py - 临时文件未清理
### 建议的修复优先级
1. **立即修复**:所有严重级别的bug,特别是可能导致程序崩溃的数组访问问题
2. **尽快修复**:中等级别的bug,特别是逻辑错误和错误处理问题
3. **代码改进**:轻微级别的bug,在时间允许时进行改进