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

13 KiB
Raw Blame History

Bug 报告

严重程度说明

  • 🔴 严重: 可能导致程序崩溃或数据丢失
  • 🟡 中等: 可能导致功能异常或错误处理不当
  • 🟢 轻微: 代码质量问题,不影响功能但需要改进

1. api.py (根目录) - 错误日志键名错误

位置

  • 第540行:entry_data_batch_delete 方法
  • 第654行:workflow_task_hand_over 方法
  • 第701行:get_upload_token 方法
  • 第745行:upload_file 方法

问题描述

🟡 中等 - 在错误日志中使用了错误的键名 data['data_list'],但这些方法中可能不存在该键。

代码示例

# 第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,需要确保它能被正确调用。

代码示例

# 第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() 会无限期阻塞,如果任务处理线程出现问题,可能导致请求永远挂起。

代码示例

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。

代码示例

res_j = res.json()
upload_url = res_j['token_and_url_list'][0]['url']
upload_token = res_j['token_and_url_list'][0]['token']

修复建议

添加检查:

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。

代码示例

url = data['data']['附件'][0]['url']

修复建议

添加检查:

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。

代码示例

action = data1['data']['Action(隐藏)']

修复建议

使用安全访问:

action = data1.get('data', {}).get('Action(隐藏)')
if not action:
    return {'msg': '缺少Action字段'}

7. app/module/module.py - 临时文件未清理

位置

第21-31行:get_captcha 方法

问题描述

🟢 轻微 - 创建了临时文件 captcha.pngpreprocessed_captcha.png,但没有清理。

代码示例

with open('captcha.png', 'wb') as f:
    f.write(response.content)
# ... 处理文件 ...
image.save('preprocessed_captcha.png')

修复建议

使用临时文件或处理完后删除:

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_namegroup_id 为空字符串,后续请求可能失败。

代码示例

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=')

修复建议

添加检查:

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)。

代码示例

now = datetime.now()
if 20 <= now.hour <= 8:
    time.sleep(1)
else:
    time.sleep(3)

修复建议

应该是:

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。

代码示例

for task in json['tasks']:
    if task['status'] == 0:
        username = task['assignee']['username']
        instance_id = task['instance_id']
        task_id = task['task_id']

修复建议

添加检查:

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。

代码示例

operate_org_id = org_res.json().get("data").get("list")[0].get("orgId")

修复建议

添加检查:

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 在循环外部初始化,导致每次页面请求都使用相同的重试计数,而不是每页独立重试。

代码示例

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 移到循环内部:

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): 这个条件判断逻辑有问题,应该检查是否还有未处理的项。

代码示例

if success + fail < len(json_data):
    continue

修复建议

这个条件判断似乎是想检查是否处理完所有项,但逻辑不正确。应该移除或修正。


14. app/tasks/delete_tasks.py - 变量作用域问题

位置

第215行:delete_car_background 方法

问题描述

🟡 中等 - 在循环外部使用了 page 变量,但 page 只在循环内部定义。

代码示例

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 在这里可用

实际上这个不是bugpage 在循环内部是可用的。但如果在循环外部使用就会有问题。


15. api.py (根目录) - 文件资源泄漏

位置

第721-747行:upload_file 方法

问题描述

🔴 严重 - 文件在循环外部打开,如果循环中发生异常或提前返回,文件可能不会被关闭,导致资源泄漏。

代码示例

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 语句确保文件总是被关闭:

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 方法

问题描述

🟡 中等 - 文件在循环外部打开,重试时文件指针已经移动到文件末尾,后续重试会读取空内容。

代码示例

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,在时间允许时进行改进