Skip to content

Conversation

@YukiRa1n
Copy link
Contributor

@YukiRa1n YukiRa1n commented Jan 2, 2026

🐛 问题描述

症状

  • 控制台显示正常发送消息,但公众号未收到消息
  • 处理时间 > 5秒的消息几乎总是失败(如 AI 图片生成、长文本生成)
  • 短消息(<5秒)正常工作

根本原因

类型不匹配

# msg.id 是整数类型
msg.id = 25302262838371742  # int

# 字典 key 使用字符串类型  
self.wexin_event_workers["25302262838371742"] = future  # str key

# 检查时类型不匹配
if msg.id in self.wexin_event_workers:
#   ^^^^^^ int != str ❌ 永远是 False

代码设计意图是做重复检测(避免微信重试时重复处理),但检查时忘记将 msg.id 转换为字符串。


✅ 修改内容

文件astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py

- if msg.id in self.wexin_event_workers:
+ if str(msg.id) in self.wexin_event_workers:

一行修改,将整数类型的 msg.id 转换为字符串后再检查。


🎯 场景对比:AI 图片生成

❌ 修改前(有 Bug)

[16:23:04] 第1次请求 → 创建 future_1 → 生成中...
[16:23:09] 微信5秒超时,第2次请求 → 创建 future_2 → 又生成...  ❌
[16:23:14] 微信再次超时,第3次请求 → 创建 future_3 → 再生成...  ❌

结果:3个 future,只有1个被设置,用户收不到图片 ❌

✅ 修改后(已修复)

[16:35:44] 第1次请求 → 创建 future → 生成中...
[16:35:49] 微信5秒超时,第2次请求 → 重用 future → 等待...  ✓
[16:35:53] 图片生成完成 → 所有请求返回 → 用户收到图片 ✅

📊 影响范围

场景 处理时间 修改前 修改后
简单对话 < 1秒 ✅ 正常 ✅ 正常
AI 短文本 1-3秒 ✅ 正常 ✅ 正常
AI 长文本 5-10秒 ❌ 概率失败 ✅ 正常
AI 图片生成 7-10秒 ❌ 几乎总是失败 ✅ 正常

🧪 测试验证

  • ✅ AI 图片生成(~9秒):从总是失败 → 成功返回
  • ✅ 长文本生成(~8秒):从概率失败 → 稳定返回
  • ✅ 简单对话(<1秒):保持正常

⚠️ 风险评估

  • ✅ 仅影响微信公众号适配器
  • ✅ 修改范围小(1行代码)
  • ✅ 向后兼容
  • ✅ 无性能影响
  • ✅ 不影响其他平台

Fixes #1679

Summary by Sourcery

Bug Fixes:

  • 修正微信公众号适配器中的消息 ID 类型处理,使重试请求能够被正确识别为重复请求,并返回已生成的结果。
Original summary in English

Summary by Sourcery

Bug Fixes:

  • Correct message ID type handling in the WeChat Official Account adapter so that retry requests are properly recognized as duplicates and return the generated result.

问题描述:
- 控制台显示正常发送消息,但公众号未收到
- 处理时间 > 5秒的消息几乎总是失败(如 AI 图片生成)
- 短消息(<5秒)正常工作

根本原因:
msg.id 是整数类型,但字典 key 使用字符串类型,导致类型不匹配。
检查时整数无法匹配字符串 key,导致每次都创建新的 future,
微信重试时无法重用,最终导致响应失败。

修复内容:
将 msg.id 转换为字符串后再检查字典
  if str(msg.id) in self.wexin_event_workers:

影响范围:
- 修复了微信重试时无法正确重用 future 的问题
- AI 图片生成、长文本生成等耗时操作现在可以正常工作
- 仅影响微信公众号适配器,其他平台不受影响

Fixes AstrBotDevs#1679
@auto-assign auto-assign bot requested review from advent259141 and anka-afk January 2, 2026 09:17
@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jan 2, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我在这里给出了一些高层次的反馈:

  • 既然你现在已经在 self.wexin_event_workers 上统一使用字符串作为 key,那么就可以去掉 cast(str | int, msg.id),直接使用已经转换好的 key(比如先执行一次 key = str(msg.id),然后在成员检查和查找时都复用它)。
  • 为了避免在对 self.wexin_event_workers 进行成员检查和查找之间出现潜在的竞态情况,建议使用 future = self.wexin_event_workers.get(key),并通过判断是否为 None 来替代单独的 in 检查和索引操作。
面向 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- Since you now standardize on string keys for `self.wexin_event_workers`, you can drop the `cast(str | int, msg.id)` and just use the already-converted key (e.g. assign `key = str(msg.id)` once and reuse it for both the membership check and lookup).
- To avoid a possible race between the membership check and the lookup on `self.wexin_event_workers`, consider using `future = self.wexin_event_workers.get(key)` and checking for `None` instead of separate `in` and indexing operations.

Sourcery 对开源项目是免费的——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English

Hey - I've left some high level feedback:

  • Since you now standardize on string keys for self.wexin_event_workers, you can drop the cast(str | int, msg.id) and just use the already-converted key (e.g. assign key = str(msg.id) once and reuse it for both the membership check and lookup).
  • To avoid a possible race between the membership check and the lookup on self.wexin_event_workers, consider using future = self.wexin_event_workers.get(key) and checking for None instead of separate in and indexing operations.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Since you now standardize on string keys for `self.wexin_event_workers`, you can drop the `cast(str | int, msg.id)` and just use the already-converted key (e.g. assign `key = str(msg.id)` once and reuse it for both the membership check and lookup).
- To avoid a possible race between the membership check and the lookup on `self.wexin_event_workers`, consider using `future = self.wexin_event_workers.get(key)` and checking for `None` instead of separate `in` and indexing operations.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot bot added the area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. label Jan 2, 2026
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Jan 2, 2026
@Soulter Soulter merged commit 3622504 into AstrBotDevs:master Jan 2, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. lgtm This PR has been approved by a maintainer size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]微信公众号概率消息不发送

2 participants