Skip to content
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

[Bug] 消息发送成功后发生异常导致graia.ariadne.util.send.Safe重复发送消息 #234

Closed
EZForever opened this issue May 7, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@EZForever
Copy link

EZForever commented May 7, 2023

问题

文档app.send_message()action参数可以决定当消息发送失败时该方法的行为,而graia.ariadne.util.send.Safe可以自动在发送失败后进行若干规避且重发消息。

for type in [AtAll, At, Poke, Forward, MultimediaElement]:
convert(chain, type)
val = await ariadne.send_message(**item.send_data, action=Ignore) # type: ignore
if val is not None:
return val

问题在于app.send_message()在发送消息成功后仍有可能产生异常(虽然这种情况极其少见,例如日志记录故障之类),这种情况下app.send_message(action=Ignore)会像消息发送失败一样返回None,导致graia.ariadne.util.send.Safe多次试图重发已经发出的消息,造成简短的消息轰炸,并可能造成风控察觉。这个行为直接把Safe变成了不安全的。

如何复现

这里借用Python的一个bug python/cpython#104231 ,以及issue中举的一个例子,构造一个日志抛异常的情形。这种情形在现实应用中也可能出现,例如使用toml读取发送内容的时候。

import tomlkit # pip install tomlkit==0.11.8

from graia.ariadne.util.send import Safe
from graia.ariadne.entry import Ariadne, WebsocketClientConfig
from graia.ariadne.event.message import FriendMessage, MessageEvent

app = Ariadne(ariadne_config(
    ********,
    '********',
    WebsocketClientConfig('http://********')
))

@app.broadcast.receiver('FriendMessage')
async def on_metacmd(app: Ariadne, event: FriendMessage) -> None:
    message = tomlkit.value('"hello"')
    await app.send_message(event, message, action = Safe)

app.launch_blocking()

之后向机器人私聊任意消息,可以观察到hello被连续回复了六次。

预期行为

最直接的workaround是令graia.ariadne.util.send.Safe使用app.send_message(action=Strict),之后自行判断哪些异常是致命的,但这样在将来可能还是会出现语义问题。

考虑到app.send_message()的作用就是发送消息,消息发送成功就应当返回成功的结果,所以更根本的解决方案是将所有消息发送成功后出现的异常降级为warning,或者至少令其不要体现在异常或返回值上。

使用环境:

  • 系统: Alpine Linux 3.17 (Podman 4.5.0)
  • MAH 版本: 2.9.1
  • Ariadne 版本: 0.11.4,最新开发版可以复现
  • Python 版本: 3.9.12
  • 其他 Graia 库版本: Amnesia 0.7.1, Broadcast 0.19.2, Launart 0.6.3, Statv 0.3.2
  • 其他 有关 库版本: tomlkit 0.11.8

日志/截图

无。

@EZForever EZForever added bug Something isn't working triage Further information is requested labels May 7, 2023
@BlueGlassBlock BlueGlassBlock removed the triage Further information is requested label May 7, 2023
@BlueGlassBlock
Copy link
Member

@EZForever 请尝试使用最新开发版进行验证

考虑到 app.send_message() 的作用就是发送消息,消息发送成功就应当返回成功的结果,所以更根本的解决方案是将所有消息发送成功后出现的异常降级为warning,或者至少令其不要体现在异常或返回值上。

很遗憾,Python 不像其他语言可以预先了解所有可能的异常/错误,所以只能暂时先如此修复

@EZForever
Copy link
Author

EZForever commented May 7, 2023

理解,这也不能算是Python语言的问题(当然Java只用Checked Exception的话当我没说),考虑到目前只有action=Safe会试图重发信息,只要这个可重试的异常列表是完备的,这个修复方案没问题。

不过issue这种情况的存在表示了app.send_message()的报错状态并不能完全代表消息发送成功与否,而这是反用户直觉的。在例如说有人自己使用action=Ignore然后判断返回值是否为None的情况下,可能会造成迷惑。建议更新action的文档app.send_message()的文档添加提示,并且列出实际代表消息发送失败的异常列表。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants