-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
fix: 修复 qq_official 消息重复消费与误拦截问题 #5899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
8f0ff7d
d8dbb15
767205b
ce6c773
1d97eae
d7f90ef
ad86f8b
5ff72ba
61464c8
c06998c
6bfbcf2
df4c8bd
5863532
fd88cc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -122,6 +122,15 @@ async def load_platform(self, platform_config: dict) -> None: | |
| ) | ||
| return | ||
|
|
||
| # 防御式处理:避免同一平台 ID 被重复加载导致消息重复消费。 | ||
| if platform_id in self._inst_map: | ||
| logger.warning( | ||
| "平台 %s(%s) 已存在实例,先终止旧实例再重载。", | ||
| platform_config["type"], | ||
| platform_id, | ||
| ) | ||
| await self.terminate_platform(platform_id) | ||
|
Comment on lines
+126
to
+132
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Since the platform instance was likely stored in platform_id = platform_config.get("id")
if not self._is_valid_platform_id(platform_id):
sanitized_id, changed = self._sanitize_platform_id(platform_id)
if sanitized_id and changed:
logger.warning(
"平台 ID %r 包含非法字符 ':' 或 '!',已替换为 %r。",
platform_id,
sanitized_id,
)
platform_config["id"] = sanitized_id
platform_id = sanitized_id # Update the local variable to the sanitized version
self.astrbot_config.save_config()
else:
logger.error(
f"平台 ID {platform_id!r} 不能为空,跳过加载该平台适配器。",
)
return |
||
|
|
||
| logger.info( | ||
| f"载入 {platform_config['type']}({platform_config['id']}) 平台适配器 ...", | ||
| ) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): 建议通过使用单一时间戳映射结构、复用浮点配置解析辅助函数,并将附件标识逻辑下沉到组件类中来简化去重设计和降低耦合度。
在不改变行为的前提下,当前的一些逻辑可以进一步简化:
1. TTL 结构:
set+deque→ 单一 dict你目前使用
_seen和_queue来实现 TTL 机制。对于较小 TTL 且单消费循环的场景,用一个dict[fingerprint, timestamp]加一个简单清理循环,更易于理解,也能避免在队列中处理元组下标:这样可以在保持现有行为(相同的指纹、相同的 TTL 语义)的同时,去掉自定义队列索引的复杂度。
2. 复用配置解析辅助函数,而不是
_safe_floatEventBus._safe_float与你在qqofficial_platform_adapter.py中的_safe_float_config存在逻辑重复。为降低跨文件的理解成本,可以考虑导入并使用共享的辅助函数(或将其移动到一个共享模块中):然后在
EventBus中:3. 将附件标识从字段级探测中解耦
_build_attachment_signature当前对Image/File的内部结构做了假设。如果Image/File能暴露一个稳定标识符,可以把这些分支逻辑移动到这些类中,让去重器只关注标识符本身:这样既可以保留指纹的丰富度,又能把与组件具体结构相关的逻辑放到数据自身所在类中,使
EventDeduplicator对数据结构不那么敏感,更易于维护。Original comment in English
issue (complexity): Consider simplifying the deduplication design by using a single timestamp map, sharing the float parsing helper, and pushing attachment identity logic into the component classes to reduce coupling.
A few parts of the new logic can be simplified without changing behavior:
1. TTL structure:
set+deque→ single dictYou’re maintaining both
_seenand_queueto enforce TTL. For a small TTL and single-consumer loop, a singledict[fingerprint, timestamp]with a simple cleanup loop is easier to reason about and avoids tuple juggling:This preserves the current behavior (same fingerprints, same TTL semantics) but removes the custom queue indexing.
2. Reuse config parsing helper instead of
_safe_floatEventBus._safe_floatduplicates logic that you already have as_safe_float_configinqqofficial_platform_adapter.py. To reduce cross-file cognitive load, consider importing and using the shared helper (or moving it to a shared module):Then in
EventBus:3. Decouple attachment identity from field-level probing
_build_attachment_signaturecurrently encodes assumptions aboutImage/Fileinternals. IfImage/Filecan expose a stable identifier, you can move this branching into those classes and keep the deduplicator focused on identifiers only:This keeps the richness of the fingerprint but moves the component-specific logic to where the data lives, making
EventDeduplicatorless “schema-aware” and easier to maintain.